diff options
290 files changed, 45074 insertions, 19118 deletions
@@ -19,7 +19,7 @@ m4/lt~obsolete.m4 autom4te.cache # downloaded files -gtest +gmock # in-tree configure-generated files Makefile @@ -27,7 +27,6 @@ src/Makefile /config.h config.log config.status -pbconfig.h libtool protobuf-lite.pc @@ -48,6 +47,8 @@ any_test.pb.* map*unittest.pb.* unittest*.pb.* cpp_test*.pb.* +src/google/protobuf/util/**/*.pb.cc +src/google/protobuf/util/**/*.pb.h *.pyc *.egg-info diff --git a/.travis.yml b/.travis.yml index 9dc99b4e..4edf3b30 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,8 @@ sudo: required +# Note: travis currently does not support listing more than one language so +# this cheats and claims to only be cpp. If they add multiple language +# support, this should probably get updated to install steps and/or +# rvm/gemfile/jdk/etc. entries rather than manually doing the work. language: cpp os: - linux @@ -22,5 +26,31 @@ env: - CONFIG=ruby21 - CONFIG=ruby22 - CONFIG=jruby +matrix: + exclude: + # It's nontrivial to programmatically install a new JDK from the command + # line on OS X, so we rely on testing on Linux for Java code. + - os: osx + env: CONFIG=java_jdk6 + - os: osx + env: CONFIG=java_jdk7 + - os: osx + env: CONFIG=java_oracle7 + - os: osx + env: CONFIG=javanano_jdk6 + - os: osx + env: CONFIG=javanano_jdk7 + - os: osx + env: CONFIG=javanano_oracle7 + # Requires installing mono, currently travis.sh is doing that with apt-get + # which doesn't work on OS X. + - os: osx + env: CONFIG=csharp + allow_failures: + # These currently do not work on OS X but are being worked on by @haberman. + - os: osx + env: CONFIG=ruby22 + - os: osx + env: CONFIG=jruby notifications: email: false diff --git a/Android.mk b/Android.mk deleted file mode 100644 index bbd15740..00000000 --- a/Android.mk +++ /dev/null @@ -1,492 +0,0 @@ -# Copyright (C) 2009 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# - -LOCAL_PATH := $(call my-dir) - -IGNORED_WARNINGS := -Wno-sign-compare -Wno-unused-parameter -Wno-sign-promo - -CC_LITE_SRC_FILES := \ - src/google/protobuf/stubs/common.cc \ - src/google/protobuf/stubs/once.cc \ - src/google/protobuf/stubs/hash.cc \ - src/google/protobuf/stubs/hash.h \ - src/google/protobuf/stubs/map-util.h \ - src/google/protobuf/stubs/stl_util-inl.h \ - src/google/protobuf/extension_set.cc \ - src/google/protobuf/generated_message_util.cc \ - src/google/protobuf/message_lite.cc \ - src/google/protobuf/repeated_field.cc \ - src/google/protobuf/wire_format_lite.cc \ - src/google/protobuf/io/coded_stream.cc \ - src/google/protobuf/io/coded_stream_inl.h \ - src/google/protobuf/io/zero_copy_stream.cc \ - src/google/protobuf/io/zero_copy_stream_impl_lite.cc - -JAVA_LITE_SRC_FILES := \ - java/src/main/java/com/google/protobuf/UninitializedMessageException.java \ - java/src/main/java/com/google/protobuf/MessageLite.java \ - java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \ - java/src/main/java/com/google/protobuf/CodedOutputStream.java \ - java/src/main/java/com/google/protobuf/ByteString.java \ - java/src/main/java/com/google/protobuf/CodedInputStream.java \ - java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java \ - java/src/main/java/com/google/protobuf/AbstractMessageLite.java \ - java/src/main/java/com/google/protobuf/FieldSet.java \ - java/src/main/java/com/google/protobuf/Internal.java \ - java/src/main/java/com/google/protobuf/WireFormat.java \ - java/src/main/java/com/google/protobuf/GeneratedMessageLite.java - -COMPILER_SRC_FILES := \ - src/google/protobuf/descriptor.cc \ - src/google/protobuf/descriptor.pb.cc \ - src/google/protobuf/descriptor_database.cc \ - src/google/protobuf/dynamic_message.cc \ - src/google/protobuf/extension_set.cc \ - src/google/protobuf/extension_set_heavy.cc \ - src/google/protobuf/generated_message_reflection.cc \ - src/google/protobuf/generated_message_util.cc \ - src/google/protobuf/message.cc \ - src/google/protobuf/message_lite.cc \ - src/google/protobuf/reflection_ops.cc \ - src/google/protobuf/repeated_field.cc \ - src/google/protobuf/service.cc \ - src/google/protobuf/text_format.cc \ - src/google/protobuf/unknown_field_set.cc \ - src/google/protobuf/wire_format.cc \ - src/google/protobuf/wire_format_lite.cc \ - src/google/protobuf/compiler/code_generator.cc \ - src/google/protobuf/compiler/command_line_interface.cc \ - src/google/protobuf/compiler/importer.cc \ - src/google/protobuf/compiler/main.cc \ - src/google/protobuf/compiler/parser.cc \ - src/google/protobuf/compiler/plugin.cc \ - src/google/protobuf/compiler/plugin.pb.cc \ - src/google/protobuf/compiler/subprocess.cc \ - src/google/protobuf/compiler/zip_writer.cc \ - src/google/protobuf/compiler/cpp/cpp_enum.cc \ - src/google/protobuf/compiler/cpp/cpp_enum_field.cc \ - src/google/protobuf/compiler/cpp/cpp_extension.cc \ - src/google/protobuf/compiler/cpp/cpp_field.cc \ - src/google/protobuf/compiler/cpp/cpp_file.cc \ - src/google/protobuf/compiler/cpp/cpp_generator.cc \ - src/google/protobuf/compiler/cpp/cpp_helpers.cc \ - src/google/protobuf/compiler/cpp/cpp_message.cc \ - src/google/protobuf/compiler/cpp/cpp_message_field.cc \ - src/google/protobuf/compiler/cpp/cpp_primitive_field.cc \ - src/google/protobuf/compiler/cpp/cpp_service.cc \ - src/google/protobuf/compiler/cpp/cpp_string_field.cc \ - src/google/protobuf/compiler/java/java_enum.cc \ - src/google/protobuf/compiler/java/java_enum_field.cc \ - src/google/protobuf/compiler/java/java_enum_field_lite.cc \ - src/google/protobuf/compiler/java/java_extension.cc \ - src/google/protobuf/compiler/java/java_field.cc \ - src/google/protobuf/compiler/java/java_file.cc \ - src/google/protobuf/compiler/java/java_generator.cc \ - src/google/protobuf/compiler/java/java_helpers.cc \ - src/google/protobuf/compiler/java/java_message.cc \ - src/google/protobuf/compiler/java/java_message_lite.cc \ - src/google/protobuf/compiler/java/java_message_builder.cc \ - src/google/protobuf/compiler/java/java_message_builder_lite.cc \ - src/google/protobuf/compiler/java/java_message_field.cc \ - src/google/protobuf/compiler/java/java_message_field_lite.cc \ - src/google/protobuf/compiler/java/java_primitive_field.cc \ - src/google/protobuf/compiler/java/java_primitive_field_lite.cc \ - src/google/protobuf/compiler/java/java_service.cc \ - src/google/protobuf/compiler/javamicro/javamicro_enum.cc \ - src/google/protobuf/compiler/javamicro/javamicro_enum_field.cc \ - src/google/protobuf/compiler/javamicro/javamicro_field.cc \ - src/google/protobuf/compiler/javamicro/javamicro_file.cc \ - src/google/protobuf/compiler/javamicro/javamicro_generator.cc \ - src/google/protobuf/compiler/javamicro/javamicro_helpers.cc \ - src/google/protobuf/compiler/javamicro/javamicro_message.cc \ - src/google/protobuf/compiler/javamicro/javamicro_message_field.cc \ - src/google/protobuf/compiler/javamicro/javamicro_primitive_field.cc \ - src/google/protobuf/compiler/javanano/javanano_enum.cc \ - src/google/protobuf/compiler/javanano/javanano_enum_field.cc \ - src/google/protobuf/compiler/javanano/javanano_extension.cc \ - src/google/protobuf/compiler/javanano/javanano_field.cc \ - src/google/protobuf/compiler/javanano/javanano_file.cc \ - src/google/protobuf/compiler/javanano/javanano_generator.cc \ - src/google/protobuf/compiler/javanano/javanano_helpers.cc \ - src/google/protobuf/compiler/javanano/javanano_message.cc \ - src/google/protobuf/compiler/javanano/javanano_message_field.cc \ - src/google/protobuf/compiler/javanano/javanano_primitive_field.cc \ - src/google/protobuf/compiler/python/python_generator.cc \ - src/google/protobuf/io/coded_stream.cc \ - src/google/protobuf/io/gzip_stream.cc \ - src/google/protobuf/io/printer.cc \ - src/google/protobuf/io/tokenizer.cc \ - src/google/protobuf/io/zero_copy_stream.cc \ - src/google/protobuf/io/zero_copy_stream_impl.cc \ - src/google/protobuf/io/zero_copy_stream_impl_lite.cc \ - src/google/protobuf/stubs/common.cc \ - src/google/protobuf/stubs/hash.cc \ - src/google/protobuf/stubs/once.cc \ - src/google/protobuf/stubs/structurally_valid.cc \ - src/google/protobuf/stubs/strutil.cc \ - src/google/protobuf/stubs/substitute.cc - -# Java nano library (for device-side users) -# ======================================================= -include $(CLEAR_VARS) - -LOCAL_MODULE := libprotobuf-java-nano -LOCAL_MODULE_TAGS := optional -LOCAL_SDK_VERSION := 8 - -LOCAL_SRC_FILES := $(call all-java-files-under, java/src/main/java/com/google/protobuf/nano) -LOCAL_SRC_FILES += $(call all-java-files-under, java/src/device/main/java/com/google/protobuf/nano) - -include $(BUILD_STATIC_JAVA_LIBRARY) - -# Java nano library (for host-side users) -# ======================================================= -include $(CLEAR_VARS) - -LOCAL_MODULE := host-libprotobuf-java-nano -LOCAL_MODULE_TAGS := optional - -LOCAL_SRC_FILES := $(call all-java-files-under, java/src/main/java/com/google/protobuf/nano) - -include $(BUILD_HOST_JAVA_LIBRARY) - -# Java micro library (for device-side users) -# ======================================================= -include $(CLEAR_VARS) - -LOCAL_MODULE := libprotobuf-java-micro -LOCAL_MODULE_TAGS := optional -LOCAL_SDK_VERSION := 8 - -LOCAL_SRC_FILES := $(call all-java-files-under, java/src/main/java/com/google/protobuf/micro) - -include $(BUILD_STATIC_JAVA_LIBRARY) - -# Java micro library (for host-side users) -# ======================================================= -include $(CLEAR_VARS) - -LOCAL_MODULE := host-libprotobuf-java-micro -LOCAL_MODULE_TAGS := optional - -LOCAL_SRC_FILES := $(call all-java-files-under, java/src/main/java/com/google/protobuf/micro) - -include $(BUILD_HOST_JAVA_LIBRARY) - -# Java lite library (for device-side users) -# ======================================================= -include $(CLEAR_VARS) - -LOCAL_MODULE := libprotobuf-java-lite -LOCAL_MODULE_TAGS := optional -LOCAL_SDK_VERSION := 8 - -LOCAL_SRC_FILES := $(JAVA_LITE_SRC_FILES) - -include $(BUILD_STATIC_JAVA_LIBRARY) - -# Java lite library (for host-side users) -# ======================================================= -include $(CLEAR_VARS) - -LOCAL_MODULE := host-libprotobuf-java-lite -LOCAL_MODULE_TAGS := optional - -LOCAL_SRC_FILES := $(JAVA_LITE_SRC_FILES) - -include $(BUILD_HOST_JAVA_LIBRARY) - -# C++ lite library -# ======================================================= -include $(CLEAR_VARS) - -LOCAL_MODULE := libprotobuf-cpp-lite -LOCAL_MODULE_TAGS := optional - -LOCAL_CPP_EXTENSION := .cc - -LOCAL_SRC_FILES := $(CC_LITE_SRC_FILES) - -LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/android \ - $(LOCAL_PATH)/src - -# Define the header files to be copied -#LOCAL_COPY_HEADERS := \ -# src/google/protobuf/stubs/once.h \ -# src/google/protobuf/stubs/common.h \ -# src/google/protobuf/io/coded_stream.h \ -# src/google/protobuf/generated_message_util.h \ -# src/google/protobuf/repeated_field.h \ -# src/google/protobuf/extension_set.h \ -# src/google/protobuf/wire_format_lite_inl.h -# -#LOCAL_COPY_HEADERS_TO := $(LOCAL_MODULE) - -LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI $(IGNORED_WARNINGS) - -# These are the minimum versions and don't need to be update. -ifeq ($(TARGET_ARCH),arm) -LOCAL_SDK_VERSION := 8 -else -# x86/mips support only available from API 9. -LOCAL_SDK_VERSION := 9 -endif -LOCAL_NDK_STL_VARIANT := stlport_static - -include $(BUILD_STATIC_LIBRARY) - -# C++ lite library (libc++ flavored for the platform) -# ======================================================= -include $(CLEAR_VARS) - -LOCAL_MODULE := libprotobuf-cpp-lite -LOCAL_MODULE_TAGS := optional - -LOCAL_CPP_EXTENSION := .cc - -LOCAL_SRC_FILES := $(CC_LITE_SRC_FILES) - -LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/android \ - $(LOCAL_PATH)/src - -LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI $(IGNORED_WARNINGS) - -include $(BUILD_SHARED_LIBRARY) - -# C++ full library -# ======================================================= -protobuf_cc_full_src_files := \ - $(CC_LITE_SRC_FILES) \ - src/google/protobuf/stubs/strutil.cc \ - src/google/protobuf/stubs/strutil.h \ - src/google/protobuf/stubs/substitute.cc \ - src/google/protobuf/stubs/substitute.h \ - src/google/protobuf/stubs/structurally_valid.cc \ - src/google/protobuf/descriptor.cc \ - src/google/protobuf/descriptor.pb.cc \ - src/google/protobuf/descriptor_database.cc \ - src/google/protobuf/dynamic_message.cc \ - src/google/protobuf/extension_set_heavy.cc \ - src/google/protobuf/generated_message_reflection.cc \ - src/google/protobuf/message.cc \ - src/google/protobuf/reflection_ops.cc \ - src/google/protobuf/service.cc \ - src/google/protobuf/text_format.cc \ - src/google/protobuf/unknown_field_set.cc \ - src/google/protobuf/wire_format.cc \ - src/google/protobuf/io/gzip_stream.cc \ - src/google/protobuf/io/printer.cc \ - src/google/protobuf/io/tokenizer.cc \ - src/google/protobuf/io/zero_copy_stream_impl.cc \ - src/google/protobuf/compiler/importer.cc \ - src/google/protobuf/compiler/parser.cc - -# C++ full library - stlport version -# ======================================================= -include $(CLEAR_VARS) - -LOCAL_MODULE := libprotobuf-cpp-full -LOCAL_MODULE_TAGS := optional -LOCAL_CPP_EXTENSION := .cc -LOCAL_SRC_FILES := $(protobuf_cc_full_src_files) -LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/android \ - external/zlib \ - $(LOCAL_PATH)/src - -# Define the header files to be copied -#LOCAL_COPY_HEADERS := \ -# src/google/protobuf/stubs/once.h \ -# src/google/protobuf/stubs/common.h \ -# src/google/protobuf/io/coded_stream.h \ -# src/google/protobuf/generated_message_util.h \ -# src/google/protobuf/repeated_field.h \ -# src/google/protobuf/extension_set.h \ -# src/google/protobuf/wire_format_lite_inl.h -# -#LOCAL_COPY_HEADERS_TO := $(LOCAL_MODULE) - -LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI $(IGNORED_WARNINGS) - -# These are the minimum versions and don't need to be update. -ifeq ($(TARGET_ARCH),arm) -LOCAL_SDK_VERSION := 8 -else -# x86/mips support only available from API 9. -LOCAL_SDK_VERSION := 9 -endif -LOCAL_NDK_STL_VARIANT := stlport_static - -include $(BUILD_STATIC_LIBRARY) - -# C++ full library - Gnustl+rtti version -# ======================================================= -include $(CLEAR_VARS) - -LOCAL_MODULE := libprotobuf-cpp-full-gnustl-rtti -LOCAL_MODULE_TAGS := optional -LOCAL_CPP_EXTENSION := .cc -LOCAL_SRC_FILES := $(protobuf_cc_full_src_files) -LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/android \ - external/zlib \ - $(LOCAL_PATH)/src - -LOCAL_CFLAGS := -frtti $(IGNORED_WARNINGS) -LOCAL_SDK_VERSION := 14 -LOCAL_NDK_STL_VARIANT := gnustl_static - -include $(BUILD_STATIC_LIBRARY) - -# C++ full library - libc++ version for the platform -# ======================================================= -include $(CLEAR_VARS) - -LOCAL_MODULE := libprotobuf-cpp-full -LOCAL_MODULE_TAGS := optional -LOCAL_CPP_EXTENSION := .cc -LOCAL_SRC_FILES := $(protobuf_cc_full_src_files) -LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/android \ - external/zlib \ - $(LOCAL_PATH)/src - -LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI $(IGNORED_WARNINGS) -LOCAL_SHARED_LIBRARIES := libz - -include $(BUILD_SHARED_LIBRARY) - -# Clean temp vars -protobuf_cc_full_src_files := - - -# Android Protocol buffer compiler, aprotoc (host executable) -# used by the build systems as $(PROTOC) defined in -# build/core/config.mk -# ======================================================= -include $(CLEAR_VARS) - -LOCAL_MODULE := aprotoc -LOCAL_MODULE_CLASS := EXECUTABLES -LOCAL_MODULE_TAGS := optional - -LOCAL_CPP_EXTENSION := .cc -LOCAL_SRC_FILES := $(COMPILER_SRC_FILES) - -LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/android \ - external/zlib \ - $(LOCAL_PATH)/src - -LOCAL_STATIC_LIBRARIES += libz - -ifneq ($(HOST_OS),windows) -LOCAL_LDLIBS := -lpthread -endif - -LOCAL_CFLAGS := $(IGNORED_WARNINGS) - -include $(BUILD_HOST_EXECUTABLE) - -# To test java proto params build rules. -# ======================================================= -include $(CLEAR_VARS) - -LOCAL_MODULE := aprotoc-test-nano-params -LOCAL_MODULE_TAGS := tests -LOCAL_SDK_VERSION := current - -LOCAL_PROTOC_OPTIMIZE_TYPE := nano - -LOCAL_SRC_FILES := \ - src/google/protobuf/unittest_import_nano.proto \ - src/google/protobuf/unittest_simple_nano.proto \ - src/google/protobuf/unittest_stringutf8_nano.proto \ - src/google/protobuf/unittest_recursive_nano.proto - - -LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/src - -LOCAL_PROTO_JAVA_OUTPUT_PARAMS := \ - java_package = $(LOCAL_PATH)/src/google/protobuf/unittest_import_nano.proto|com.google.protobuf.nano, \ - java_outer_classname = $(LOCAL_PATH)/src/google/protobuf/unittest_import_nano.proto|UnittestImportNano - -include $(BUILD_STATIC_JAVA_LIBRARY) - -# To test Android-specific nanoproto features. -# ======================================================= -include $(CLEAR_VARS) - -# Parcelable messages -LOCAL_MODULE := android-nano-test-parcelable -LOCAL_MODULE_TAGS := tests -LOCAL_SDK_VERSION := current - -LOCAL_PROTOC_OPTIMIZE_TYPE := nano - -LOCAL_SRC_FILES := src/google/protobuf/unittest_simple_nano.proto - -LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/src - -LOCAL_PROTO_JAVA_OUTPUT_PARAMS := \ - parcelable_messages = true - -include $(BUILD_STATIC_JAVA_LIBRARY) - -include $(CLEAR_VARS) - -# Parcelable and extendable messages -LOCAL_MODULE := android-nano-test-parcelable-extendable -LOCAL_MODULE_TAGS := tests -LOCAL_SDK_VERSION := current - -LOCAL_PROTOC_OPTIMIZE_TYPE := nano - -LOCAL_SRC_FILES := src/google/protobuf/unittest_extension_nano.proto - -LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/src - -LOCAL_PROTO_JAVA_OUTPUT_PARAMS := \ - parcelable_messages = true, \ - store_unknown_fields = true - -include $(BUILD_STATIC_JAVA_LIBRARY) - -include $(CLEAR_VARS) - -# Test APK -LOCAL_PACKAGE_NAME := NanoAndroidTest - -LOCAL_SDK_VERSION := 8 - -LOCAL_MODULE_TAGS := tests - -LOCAL_SRC_FILES := $(call all-java-files-under, java/src/device/test/java/com/google/protobuf/nano) - -LOCAL_MANIFEST_FILE := java/src/device/test/AndroidManifest.xml - -LOCAL_STATIC_JAVA_LIBRARIES := libprotobuf-java-nano \ - android-nano-test-parcelable \ - android-nano-test-parcelable-extendable - -LOCAL_DEX_PREOPT := false - -include $(BUILD_PACKAGE) - -# 2.3.0 prebuilts for backwards compatibility. -include $(LOCAL_PATH)/prebuilts/Android.mk @@ -0,0 +1,405 @@ +# Bazel (http://bazel.io/) BUILD file for Protobuf. + +licenses(["notice"]) + +COPTS = [ + "-DHAVE_PTHREAD", + "-Wall", + "-Wwrite-strings", + "-Woverloaded-virtual", + "-Wno-sign-compare", + "-Wno-error=unused-function", +] + +# Bazel should provide portable link_opts for pthread. +LINK_OPTS = ["-lpthread"] + +cc_library( + name = "protobuf_lite", + srcs = [ + # AUTOGEN(protobuf_lite_srcs) + "src/google/protobuf/arena.cc", + "src/google/protobuf/arenastring.cc", + "src/google/protobuf/extension_set.cc", + "src/google/protobuf/generated_message_util.cc", + "src/google/protobuf/io/coded_stream.cc", + "src/google/protobuf/io/zero_copy_stream.cc", + "src/google/protobuf/io/zero_copy_stream_impl_lite.cc", + "src/google/protobuf/message_lite.cc", + "src/google/protobuf/repeated_field.cc", + "src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc", + "src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc", + "src/google/protobuf/stubs/bytestream.cc", + "src/google/protobuf/stubs/common.cc", + "src/google/protobuf/stubs/once.cc", + "src/google/protobuf/stubs/status.cc", + "src/google/protobuf/stubs/statusor.cc", + "src/google/protobuf/stubs/stringpiece.cc", + "src/google/protobuf/stubs/stringprintf.cc", + "src/google/protobuf/stubs/strutil.cc", + "src/google/protobuf/stubs/time.cc", + "src/google/protobuf/wire_format_lite.cc", + ], + copts = COPTS, + includes = ["src/"], + linkopts = LINK_OPTS, + visibility = ["//visibility:public"], +) + +cc_library( + name = "protobuf", + srcs = [ + # AUTOGEN(protobuf_srcs) + "src/google/protobuf/any.cc", + "src/google/protobuf/any.pb.cc", + "src/google/protobuf/api.pb.cc", + "src/google/protobuf/compiler/importer.cc", + "src/google/protobuf/compiler/parser.cc", + "src/google/protobuf/descriptor.cc", + "src/google/protobuf/descriptor.pb.cc", + "src/google/protobuf/descriptor_database.cc", + "src/google/protobuf/duration.pb.cc", + "src/google/protobuf/dynamic_message.cc", + "src/google/protobuf/empty.pb.cc", + "src/google/protobuf/extension_set_heavy.cc", + "src/google/protobuf/field_mask.pb.cc", + "src/google/protobuf/generated_message_reflection.cc", + "src/google/protobuf/io/gzip_stream.cc", + "src/google/protobuf/io/printer.cc", + "src/google/protobuf/io/strtod.cc", + "src/google/protobuf/io/tokenizer.cc", + "src/google/protobuf/io/zero_copy_stream_impl.cc", + "src/google/protobuf/map_field.cc", + "src/google/protobuf/message.cc", + "src/google/protobuf/reflection_ops.cc", + "src/google/protobuf/service.cc", + "src/google/protobuf/source_context.pb.cc", + "src/google/protobuf/struct.pb.cc", + "src/google/protobuf/stubs/mathlimits.cc", + "src/google/protobuf/stubs/structurally_valid.cc", + "src/google/protobuf/stubs/substitute.cc", + "src/google/protobuf/text_format.cc", + "src/google/protobuf/timestamp.pb.cc", + "src/google/protobuf/type.pb.cc", + "src/google/protobuf/unknown_field_set.cc", + "src/google/protobuf/util/field_comparator.cc", + "src/google/protobuf/util/internal/datapiece.cc", + "src/google/protobuf/util/internal/default_value_objectwriter.cc", + "src/google/protobuf/util/internal/error_listener.cc", + "src/google/protobuf/util/internal/field_mask_utility.cc", + "src/google/protobuf/util/internal/json_escaping.cc", + "src/google/protobuf/util/internal/json_objectwriter.cc", + "src/google/protobuf/util/internal/json_stream_parser.cc", + "src/google/protobuf/util/internal/object_writer.cc", + "src/google/protobuf/util/internal/protostream_objectsource.cc", + "src/google/protobuf/util/internal/protostream_objectwriter.cc", + "src/google/protobuf/util/internal/type_info.cc", + "src/google/protobuf/util/internal/type_info_test_helper.cc", + "src/google/protobuf/util/internal/utility.cc", + "src/google/protobuf/util/json_util.cc", + "src/google/protobuf/util/message_differencer.cc", + "src/google/protobuf/util/type_resolver_util.cc", + "src/google/protobuf/wire_format.cc", + "src/google/protobuf/wrappers.pb.cc", + ], + copts = COPTS, + includes = ["src/"], + linkopts = LINK_OPTS, + visibility = ["//visibility:public"], + deps = [":protobuf_lite"], +) + +cc_library( + name = "protoc_lib", + srcs = [ + # AUTOGEN(protoc_lib_srcs) + "src/google/protobuf/compiler/code_generator.cc", + "src/google/protobuf/compiler/command_line_interface.cc", + "src/google/protobuf/compiler/cpp/cpp_enum.cc", + "src/google/protobuf/compiler/cpp/cpp_enum_field.cc", + "src/google/protobuf/compiler/cpp/cpp_extension.cc", + "src/google/protobuf/compiler/cpp/cpp_field.cc", + "src/google/protobuf/compiler/cpp/cpp_file.cc", + "src/google/protobuf/compiler/cpp/cpp_generator.cc", + "src/google/protobuf/compiler/cpp/cpp_helpers.cc", + "src/google/protobuf/compiler/cpp/cpp_map_field.cc", + "src/google/protobuf/compiler/cpp/cpp_message.cc", + "src/google/protobuf/compiler/cpp/cpp_message_field.cc", + "src/google/protobuf/compiler/cpp/cpp_primitive_field.cc", + "src/google/protobuf/compiler/cpp/cpp_service.cc", + "src/google/protobuf/compiler/cpp/cpp_string_field.cc", + "src/google/protobuf/compiler/csharp/csharp_enum.cc", + "src/google/protobuf/compiler/csharp/csharp_enum_field.cc", + "src/google/protobuf/compiler/csharp/csharp_extension.cc", + "src/google/protobuf/compiler/csharp/csharp_field_base.cc", + "src/google/protobuf/compiler/csharp/csharp_generator.cc", + "src/google/protobuf/compiler/csharp/csharp_helpers.cc", + "src/google/protobuf/compiler/csharp/csharp_message.cc", + "src/google/protobuf/compiler/csharp/csharp_message_field.cc", + "src/google/protobuf/compiler/csharp/csharp_primitive_field.cc", + "src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc", + "src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc", + "src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc", + "src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc", + "src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc", + "src/google/protobuf/compiler/csharp/csharp_writer.cc", + "src/google/protobuf/compiler/java/java_context.cc", + "src/google/protobuf/compiler/java/java_doc_comment.cc", + "src/google/protobuf/compiler/java/java_enum.cc", + "src/google/protobuf/compiler/java/java_enum_field.cc", + "src/google/protobuf/compiler/java/java_enum_field_lite.cc", + "src/google/protobuf/compiler/java/java_extension.cc", + "src/google/protobuf/compiler/java/java_field.cc", + "src/google/protobuf/compiler/java/java_file.cc", + "src/google/protobuf/compiler/java/java_generator.cc", + "src/google/protobuf/compiler/java/java_generator_factory.cc", + "src/google/protobuf/compiler/java/java_helpers.cc", + "src/google/protobuf/compiler/java/java_lazy_message_field.cc", + "src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc", + "src/google/protobuf/compiler/java/java_map_field.cc", + "src/google/protobuf/compiler/java/java_map_field_lite.cc", + "src/google/protobuf/compiler/java/java_message.cc", + "src/google/protobuf/compiler/java/java_message_builder.cc", + "src/google/protobuf/compiler/java/java_message_builder_lite.cc", + "src/google/protobuf/compiler/java/java_message_field.cc", + "src/google/protobuf/compiler/java/java_message_field_lite.cc", + "src/google/protobuf/compiler/java/java_message_lite.cc", + "src/google/protobuf/compiler/java/java_name_resolver.cc", + "src/google/protobuf/compiler/java/java_primitive_field.cc", + "src/google/protobuf/compiler/java/java_primitive_field_lite.cc", + "src/google/protobuf/compiler/java/java_service.cc", + "src/google/protobuf/compiler/java/java_shared_code_generator.cc", + "src/google/protobuf/compiler/java/java_string_field.cc", + "src/google/protobuf/compiler/java/java_string_field_lite.cc", + "src/google/protobuf/compiler/javanano/javanano_enum.cc", + "src/google/protobuf/compiler/javanano/javanano_enum_field.cc", + "src/google/protobuf/compiler/javanano/javanano_extension.cc", + "src/google/protobuf/compiler/javanano/javanano_field.cc", + "src/google/protobuf/compiler/javanano/javanano_file.cc", + "src/google/protobuf/compiler/javanano/javanano_generator.cc", + "src/google/protobuf/compiler/javanano/javanano_helpers.cc", + "src/google/protobuf/compiler/javanano/javanano_map_field.cc", + "src/google/protobuf/compiler/javanano/javanano_message.cc", + "src/google/protobuf/compiler/javanano/javanano_message_field.cc", + "src/google/protobuf/compiler/javanano/javanano_primitive_field.cc", + "src/google/protobuf/compiler/objectivec/objectivec_enum.cc", + "src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc", + "src/google/protobuf/compiler/objectivec/objectivec_extension.cc", + "src/google/protobuf/compiler/objectivec/objectivec_field.cc", + "src/google/protobuf/compiler/objectivec/objectivec_file.cc", + "src/google/protobuf/compiler/objectivec/objectivec_generator.cc", + "src/google/protobuf/compiler/objectivec/objectivec_helpers.cc", + "src/google/protobuf/compiler/objectivec/objectivec_map_field.cc", + "src/google/protobuf/compiler/objectivec/objectivec_message.cc", + "src/google/protobuf/compiler/objectivec/objectivec_message_field.cc", + "src/google/protobuf/compiler/objectivec/objectivec_oneof.cc", + "src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc", + "src/google/protobuf/compiler/plugin.cc", + "src/google/protobuf/compiler/plugin.pb.cc", + "src/google/protobuf/compiler/python/python_generator.cc", + "src/google/protobuf/compiler/ruby/ruby_generator.cc", + "src/google/protobuf/compiler/subprocess.cc", + "src/google/protobuf/compiler/zip_writer.cc", + ], + copts = COPTS, + includes = ["src/"], + linkopts = LINK_OPTS, + visibility = ["//visibility:public"], + deps = [":protobuf"], +) + +cc_binary( + name = "protoc", + srcs = ["src/google/protobuf/compiler/main.cc"], + linkopts = LINK_OPTS, + visibility = ["//visibility:public"], + deps = [":protoc_lib"], +) + +WELL_KNOWN_PROTOS = [ + # AUTOGEN(well_known_protos) + "google/protobuf/any.proto", + "google/protobuf/api.proto", + "google/protobuf/compiler/plugin.proto", + "google/protobuf/descriptor.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", +] + +################################################################################ +# Tests +################################################################################ + +LITE_TEST_PROTOS = [ + # AUTOGEN(lite_test_protos) + "google/protobuf/map_lite_unittest.proto", + "google/protobuf/unittest_import_lite.proto", + "google/protobuf/unittest_import_public_lite.proto", + "google/protobuf/unittest_lite.proto", +] + +TEST_PROTOS = [ + # AUTOGEN(test_protos) + "google/protobuf/any_test.proto", + "google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto", + "google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto", + "google/protobuf/map_proto2_unittest.proto", + "google/protobuf/map_unittest.proto", + "google/protobuf/unittest.proto", + "google/protobuf/unittest_arena.proto", + "google/protobuf/unittest_custom_options.proto", + "google/protobuf/unittest_drop_unknown_fields.proto", + "google/protobuf/unittest_embed_optimize_for.proto", + "google/protobuf/unittest_empty.proto", + "google/protobuf/unittest_enormous_descriptor.proto", + "google/protobuf/unittest_import.proto", + "google/protobuf/unittest_import_public.proto", + "google/protobuf/unittest_lite_imports_nonlite.proto", + "google/protobuf/unittest_mset.proto", + "google/protobuf/unittest_no_arena.proto", + "google/protobuf/unittest_no_arena_import.proto", + "google/protobuf/unittest_no_field_presence.proto", + "google/protobuf/unittest_no_generic_services.proto", + "google/protobuf/unittest_optimize_for.proto", + "google/protobuf/unittest_preserve_unknown_enum.proto", + "google/protobuf/unittest_preserve_unknown_enum2.proto", + "google/protobuf/unittest_proto3_arena.proto", + "google/protobuf/unittest_well_known_types.proto", + "google/protobuf/util/internal/testdata/anys.proto", + "google/protobuf/util/internal/testdata/books.proto", + "google/protobuf/util/internal/testdata/default_value.proto", + "google/protobuf/util/internal/testdata/default_value_test.proto", + "google/protobuf/util/internal/testdata/field_mask.proto", + "google/protobuf/util/internal/testdata/maps.proto", + "google/protobuf/util/internal/testdata/struct.proto", + "google/protobuf/util/internal/testdata/timestamp_duration.proto", + "google/protobuf/util/json_format_proto3.proto", +] + +PROTOS = LITE_TEST_PROTOS + TEST_PROTOS + +INPUTS = PROTOS + WELL_KNOWN_PROTOS + +OUTPUTS = ["src/" + x[:-5] + "pb.h" for x in PROTOS] + \ + ["src/" + x[:-5] + "pb.cc" for x in PROTOS] + +genrule( + name = "gen_test_protos", + srcs = ["src/" + x for x in INPUTS], + outs = OUTPUTS, + cmd = + "$(location :protoc) --cpp_out=$(@D)/src" + + "".join([" -I" + x + "=$(location src/" + x + ")" for x in INPUTS]) + + "".join([" $(location src/" + x + ")" for x in PROTOS]), + tools = [":protoc"], +) + +COMMON_TEST_SRCS = [ + # AUTOGEN(common_test_srcs) + "src/google/protobuf/arena_test_util.cc", + "src/google/protobuf/map_test_util.cc", + "src/google/protobuf/test_util.cc", + "src/google/protobuf/testing/file.cc", + "src/google/protobuf/testing/googletest.cc", +] + +cc_binary( + name = "test_plugin", + srcs = [ + # AUTOGEN(test_plugin_srcs) + "src/google/protobuf/compiler/mock_code_generator.cc", + "src/google/protobuf/compiler/test_plugin.cc", + "src/google/protobuf/testing/file.cc", + ], + deps = [ + ":protobuf", + ":protoc_lib", + "//external:gtest", + ], +) + +cc_test( + name = "protobuf_test", + srcs = OUTPUTS + COMMON_TEST_SRCS + [ + # AUTOGEN(test_srcs) + "src/google/protobuf/any_test.cc", + "src/google/protobuf/arena_unittest.cc", + "src/google/protobuf/arenastring_unittest.cc", + "src/google/protobuf/compiler/command_line_interface_unittest.cc", + "src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc", + "src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc", + "src/google/protobuf/compiler/cpp/cpp_unittest.cc", + "src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc", + "src/google/protobuf/compiler/importer_unittest.cc", + "src/google/protobuf/compiler/java/java_doc_comment_unittest.cc", + "src/google/protobuf/compiler/java/java_plugin_unittest.cc", + "src/google/protobuf/compiler/mock_code_generator.cc", + "src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc", + "src/google/protobuf/compiler/parser_unittest.cc", + "src/google/protobuf/compiler/python/python_plugin_unittest.cc", + "src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc", + "src/google/protobuf/descriptor_database_unittest.cc", + "src/google/protobuf/descriptor_unittest.cc", + "src/google/protobuf/drop_unknown_fields_test.cc", + "src/google/protobuf/dynamic_message_unittest.cc", + "src/google/protobuf/extension_set_unittest.cc", + "src/google/protobuf/generated_message_reflection_unittest.cc", + "src/google/protobuf/io/coded_stream_unittest.cc", + "src/google/protobuf/io/printer_unittest.cc", + "src/google/protobuf/io/tokenizer_unittest.cc", + "src/google/protobuf/io/zero_copy_stream_unittest.cc", + "src/google/protobuf/map_field_test.cc", + "src/google/protobuf/map_test.cc", + "src/google/protobuf/message_unittest.cc", + "src/google/protobuf/no_field_presence_test.cc", + "src/google/protobuf/preserve_unknown_enum_test.cc", + "src/google/protobuf/proto3_arena_unittest.cc", + "src/google/protobuf/reflection_ops_unittest.cc", + "src/google/protobuf/repeated_field_reflection_unittest.cc", + "src/google/protobuf/repeated_field_unittest.cc", + "src/google/protobuf/stubs/bytestream_unittest.cc", + "src/google/protobuf/stubs/common_unittest.cc", + "src/google/protobuf/stubs/once_unittest.cc", + "src/google/protobuf/stubs/status_test.cc", + "src/google/protobuf/stubs/statusor_test.cc", + "src/google/protobuf/stubs/stringpiece_unittest.cc", + "src/google/protobuf/stubs/stringprintf_unittest.cc", + "src/google/protobuf/stubs/structurally_valid_unittest.cc", + "src/google/protobuf/stubs/strutil_unittest.cc", + "src/google/protobuf/stubs/template_util_unittest.cc", + "src/google/protobuf/stubs/time_test.cc", + "src/google/protobuf/stubs/type_traits_unittest.cc", + "src/google/protobuf/text_format_unittest.cc", + "src/google/protobuf/unknown_field_set_unittest.cc", + "src/google/protobuf/util/field_comparator_test.cc", + "src/google/protobuf/util/internal/default_value_objectwriter_test.cc", + "src/google/protobuf/util/internal/json_objectwriter_test.cc", + "src/google/protobuf/util/internal/json_stream_parser_test.cc", + "src/google/protobuf/util/internal/protostream_objectsource_test.cc", + "src/google/protobuf/util/internal/protostream_objectwriter_test.cc", + "src/google/protobuf/util/internal/type_info_test_helper.cc", + "src/google/protobuf/util/json_util_test.cc", + "src/google/protobuf/util/type_resolver_util_test.cc", + "src/google/protobuf/well_known_types_unittest.cc", + "src/google/protobuf/wire_format_unittest.cc", + ], + copts = COPTS, + data = [ + ":test_plugin", + ], + includes = [ + "src/", + ], + linkopts = LINK_OPTS, + deps = [ + ":protobuf", + ":protoc_lib", + "//external:gtest_main", + ], +) @@ -8,8 +8,6 @@ This license applies to all parts of Protocol Buffers except the following: src/google/protobuf/stubs/atomicops_internals_aix.h. This file is copyrighted by Bloomberg Finance LP. - - Andorid.mk, which is copyrighted by The Android Open Source Project. - Copyright 2014, Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/Makefile.am b/Makefile.am index 084fca6b..37862005 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,28 +8,29 @@ AUTOMAKE_OPTIONS = foreign # the right time. SUBDIRS = . src -# Always include gtest in distributions. +# Always include gmock in distributions. DIST_SUBDIRS = $(subdirs) src conformance -# Build gtest before we build protobuf tests. We don't add gtest to SUBDIRS -# because then "make check" would also build and run all of gtest's own tests, +# Build gmock before we build protobuf tests. We don't add gmock to SUBDIRS +# because then "make check" would also build and run all of gmock's own tests, # which takes a lot of time and is generally not useful to us. Also, we don't -# want "make install" to recurse into gtest since we don't want to overwrite -# the installed version of gtest if there is one. +# want "make install" to recurse into gmock since we don't want to overwrite +# the installed version of gmock if there is one. check-local: - @echo "Making lib/libgtest.a lib/libgtest_main.a in gtest" - @cd gtest && $(MAKE) $(AM_MAKEFLAGS) lib/libgtest.la lib/libgtest_main.la + @echo "Making lib/libgmock.a lib/libgmock_main.a in gmock" + @cd gmock && $(MAKE) $(AM_MAKEFLAGS) lib/libgmock.la lib/libgmock_main.la + @cd gmock/gtest && $(MAKE) $(AM_MAKEFLAGS) lib/libgtest.la lib/libgtest_main.la -# We would like to clean gtest when "make clean" is invoked. But we have to +# We would like to clean gmock when "make clean" is invoked. But we have to # be careful because clean-local is also invoked during "make distclean", but -# "make distclean" already recurses into gtest because it's listed among the -# DIST_SUBDIRS. distclean will delete gtest/Makefile, so if we then try to +# "make distclean" already recurses into gmock because it's listed among the +# DIST_SUBDIRS. distclean will delete gmock/Makefile, so if we then try to # cd to the directory again and "make clean" it will fail. So, check that the # Makefile exists before recursing. clean-local: - @if test -e gtest/Makefile; then \ - echo "Making clean in gtest"; \ - cd gtest && $(MAKE) $(AM_MAKEFLAGS) clean; \ + @if test -e gmock/Makefile; then \ + echo "Making clean in gmock"; \ + cd gmock && $(MAKE) $(AM_MAKEFLAGS) clean; \ fi; \ if test -e conformance/Makefile; then \ echo "Making clean in conformance"; \ @@ -506,14 +507,10 @@ objectivec_EXTRA_DIST= \ objectivec/GPBDictionary.h \ objectivec/GPBDictionary.m \ objectivec/GPBDictionary_PackagePrivate.h \ - objectivec/GPBExtensionField.h \ - objectivec/GPBExtensionField.m \ - objectivec/GPBExtensionField_PackagePrivate.h \ + objectivec/GPBExtensionInternals.h \ + objectivec/GPBExtensionInternals.m \ objectivec/GPBExtensionRegistry.h \ objectivec/GPBExtensionRegistry.m \ - objectivec/GPBField.h \ - objectivec/GPBField.m \ - objectivec/GPBField_PackagePrivate.h \ objectivec/GPBMessage.h \ objectivec/GPBMessage.m \ objectivec/GPBMessage_PackagePrivate.h \ @@ -523,7 +520,10 @@ objectivec_EXTRA_DIST= \ objectivec/GPBRootObject.h \ objectivec/GPBRootObject.m \ objectivec/GPBRootObject_PackagePrivate.h \ - objectivec/GPBTypes.h \ + objectivec/GPBRuntimeTypes.h \ + objectivec/GPBUnknownField.h \ + objectivec/GPBUnknownField.m \ + objectivec/GPBUnknownField_PackagePrivate.h \ objectivec/GPBUnknownFieldSet.h \ objectivec/GPBUnknownFieldSet.m \ objectivec/GPBUnknownFieldSet_PackagePrivate.h \ @@ -547,8 +547,6 @@ objectivec_EXTRA_DIST= \ objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme \ objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme \ objectivec/README.md \ - objectivec/Tests/Filter1.txt \ - objectivec/Tests/Filter2.txt \ objectivec/Tests/golden_message \ objectivec/Tests/golden_packed_fields_message \ objectivec/Tests/GPBARCUnittestProtos.m \ @@ -564,7 +562,6 @@ objectivec_EXTRA_DIST= \ 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 \ @@ -583,21 +580,19 @@ objectivec_EXTRA_DIST= \ 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/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/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/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 \ @@ -741,39 +736,33 @@ ruby_EXTRA_DIST= \ all_EXTRA_DIST=$(csharp_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 \ - generate_descriptor_proto.sh \ - README.md \ - INSTALL.txt \ - LICENSE \ - CONTRIBUTORS.txt \ - CHANGES.txt \ - config.h.include \ - editors/README.txt \ - editors/proto.vim \ - editors/protobuf-mode.el \ - vsprojects/config.h \ - vsprojects/google/protobuf/stubs/pbconfig.h \ - vsprojects/extract_includes.bat \ - vsprojects/libprotobuf.vcproj \ - vsprojects/libprotobuf-lite.vcproj \ - vsprojects/libprotoc.vcproj \ - vsprojects/protobuf.sln \ - vsprojects/protoc.vcproj \ - vsprojects/readme.txt \ - vsprojects/test_plugin.vcproj \ - vsprojects/tests.vcproj \ - vsprojects/lite-test.vcproj \ - vsprojects/convert2008to2005.sh \ - examples/README.txt \ - examples/Makefile \ - examples/addressbook.proto \ - examples/add_person.cc \ - examples/list_people.cc \ - examples/AddPerson.java \ - examples/ListPeople.java \ - examples/add_person.py \ +EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST) \ + autogen.sh \ + generate_descriptor_proto.sh \ + README.md \ + INSTALL.txt \ + LICENSE \ + CONTRIBUTORS.txt \ + CHANGES.txt \ + update_file_lists.sh \ + cmake/CMakeLists.txt \ + cmake/libprotobuf.cmake \ + cmake/libprotobuf-lite.cmake \ + cmake/libprotoc.cmake \ + cmake/protoc.cmake \ + cmake/README.md \ + cmake/tests.cmake \ + editors/README.txt \ + editors/proto.vim \ + editors/protobuf-mode.el \ + examples/README.txt \ + examples/Makefile \ + examples/addressbook.proto \ + examples/add_person.cc \ + examples/list_people.cc \ + examples/AddPerson.java \ + examples/ListPeople.java \ + examples/add_person.py \ examples/list_people.py # Deletes all the files generated by autogen.sh. diff --git a/Protobuf.podspec b/Protobuf.podspec index 6fe77f88..b6b831c2 100644 --- a/Protobuf.podspec +++ b/Protobuf.podspec @@ -5,7 +5,7 @@ # dependent projects use the :git notation to refer to the library. Pod::Spec.new do |s| s.name = 'Protobuf' - s.version = '3.0.0' + s.version = '3.0.0-alpha-4-pre' s.summary = 'Protocol Buffers v.3 runtime library for Objective-C.' s.homepage = 'https://github.com/google/protobuf' s.license = 'New BSD' @@ -13,23 +13,23 @@ Pod::Spec.new do |s| s.source_files = 'objectivec/*.{h,m}', 'objectivec/google/protobuf/Any.pbobjc.{h,m}', + 'objectivec/google/protobuf/Api.pbobjc.{h,m}', 'objectivec/google/protobuf/Descriptor.pbobjc.{h,m}', 'objectivec/google/protobuf/Duration.pbobjc.h', 'objectivec/google/protobuf/Empty.pbobjc.{h,m}', 'objectivec/google/protobuf/FieldMask.pbobjc.{h,m}', 'objectivec/google/protobuf/SourceContext.pbobjc.{h,m}', + 'objectivec/google/protobuf/Struct.pbobjc.{h,m}', 'objectivec/google/protobuf/Timestamp.pbobjc.h', + 'objectivec/google/protobuf/Type.pbobjc.{h,m}' 'objectivec/google/protobuf/Wrappers.pbobjc.{h,m}' # Timestamp.pbobjc.m and Duration.pbobjc.m are #imported by GPBWellKnownTypes.m. So we can't # compile them (duplicate symbols), but we need them available for the importing: s.preserve_paths = 'objectivec/google/protobuf/Duration.pbobjc.m', 'objectivec/google/protobuf/Timestamp.pbobjc.m' # The following would cause duplicate symbol definitions. GPBProtocolBuffers is expected to be - # left out, as it's an umbrella implementation file. For Api, Struct and Type, see issue #449. - s.exclude_files = 'objectivec/GPBProtocolBuffers.m', - 'objectivec/google/protobuf/Api.pbobjc.{h,m}', - 'objectivec/google/protobuf/Struct.pbobjc.{h,m}', - 'objectivec/google/protobuf/Type.pbobjc.{h,m}' + # left out, as it's an umbrella implementation file. + s.exclude_files = 'objectivec/GPBProtocolBuffers.m' s.header_mappings_dir = 'objectivec' s.ios.deployment_target = '6.0' @@ -1,7 +1,7 @@ Protocol Buffers - Google's data interchange format =================================================== -[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf) +[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf) [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf) Copyright 2008 Google Inc. @@ -15,12 +15,12 @@ first: $ ./autogen.sh -This will download gtest source (which is used for C++ Protocol Buffer +This will download gmock source (which is used for C++ Protocol Buffer unit-tests) to the current directory and run automake, autoconf, etc. to generate the configure script and various template makefiles. You can skip this step if you are using a release package (which already -contains gtest and the configure script). +contains gmock and the configure script). To build and install the C++ Protocol Buffer runtime and the Protocol Buffer compiler (protoc) execute the following: @@ -156,7 +156,7 @@ For advanced usage information on configure and make, see INSTALL.txt. C++ Installation - Windows -------------------------- -If you are using Microsoft Visual C++, see vsprojects/readme.txt. +If you are using Microsoft Visual C++, see cmake/README.md. If you are using Cygwin or MinGW, follow the Unix installation instructions, above. diff --git a/WORKSPACE b/WORKSPACE new file mode 100644 index 00000000..f72f239a --- /dev/null +++ b/WORKSPACE @@ -0,0 +1,16 @@ +new_http_archive( + name = "gmock_archive", + url = "https://googlemock.googlecode.com/files/gmock-1.7.0.zip", + sha256 = "26fcbb5925b74ad5fc8c26b0495dfc96353f4d553492eb97e85a8a6d2f43095b", + build_file = "gmock.BUILD", +) + +bind( + name = "gtest", + actual = "@gmock_archive//:gtest", +) + +bind( + name = "gtest_main", + actual = "@gmock_archive//:gtest_main", +) diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..476a1179 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,34 @@ +# Only test one combination: "Visual Studio 12 + Win64 + Debug + DLL". We can
+# test more combinations but AppVeyor just takes too long to finish (each
+# combination takes ~15mins).
+platform:
+ - Win64
+
+configuration:
+ - Debug
+
+environment:
+ matrix:
+ - BUILD_DLL: ON
+
+install:
+ - ps: Start-FileDownload https://googlemock.googlecode.com/files/gmock-1.7.0.zip
+ - 7z x gmock-1.7.0.zip
+ - rename gmock-1.7.0 gmock
+
+before_build:
+ - if %platform%==Win32 set generator=Visual Studio 12
+ - if %platform%==Win64 set generator=Visual Studio 12 Win64
+ - if %platform%==Win32 set vcplatform=Win32
+ - if %platform%==Win64 set vcplatform=x64
+
+build_script:
+ - mkdir build_msvc
+ - cd build_msvc
+ - cmake -G "%generator%" -DBUILD_SHARED_LIBS=%BUILD_DLL% ../cmake
+ - msbuild protobuf.sln /p:Platform=%vcplatform% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
+ - cd %configuration%
+ - tests.exe
+
+skip_commits:
+ message: /.*\[skip appveyor\].*/
@@ -15,27 +15,18 @@ __EOF__ exit 1 fi -# Check that gtest is present. Usually it is already there since the +# Check that gmock is present. Usually it is already there since the # directory is set up as an SVN external. -if test ! -e gtest; then - echo "Google Test not present. Fetching gtest-1.7.0 from the web..." - curl -O https://googletest.googlecode.com/files/gtest-1.7.0.zip - unzip -q gtest-1.7.0.zip - rm gtest-1.7.0.zip - mv gtest-1.7.0 gtest +if test ! -e gmock; then + echo "Google Mock not present. Fetching gmock-1.7.0 from the web..." + curl -O https://googlemock.googlecode.com/files/gmock-1.7.0.zip + unzip -q gmock-1.7.0.zip + rm gmock-1.7.0.zip + mv gmock-1.7.0 gmock fi set -ex -# Temporary hack: Must change C runtime library to "multi-threaded DLL", -# otherwise it will be set to "multi-threaded static" when MSVC upgrades -# the project file to MSVC 2005/2008. vladl of Google Test says gtest will -# probably change their default to match, then this will be unnecessary. -# One of these mappings converts the debug configuration and the other -# converts the release configuration. I don't know which is which. -sed -i -e 's/RuntimeLibrary="5"/RuntimeLibrary="3"/g; - s/RuntimeLibrary="4"/RuntimeLibrary="2"/g;' gtest/msvc/*.vcproj - # TODO(kenton): Remove the ",no-obsolete" part and fix the resulting warnings. autoreconf -f -i -Wall,no-obsolete diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt new file mode 100644 index 00000000..d36292df --- /dev/null +++ b/cmake/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 2.8) + +project(protobuf C CXX) + +option(BUILD_TESTING "Build tests" ON) +option(BUILD_SHARED_LIBS "Build Shared Libraries" OFF) +if (MSVC) + option(ZLIB "Build with zlib support" OFF) +endif (MSVC) + +add_definitions(-DGOOGLE_PROTOBUF_CMAKE_BUILD) + +find_package(Threads REQUIRED) +if (CMAKE_USE_PTHREADS_INIT) + add_definitions(-DHAVE_PTHREAD) +endif (CMAKE_USE_PTHREADS_INIT) + +if (MSVC) + if (ZLIB) + set(HAVE_ZLIB 1) + find_path(ZLIB_INCLUDE_DIRECTORIES zlib.h ${protobuf_SOURCE_DIR}) + find_library(ZLIB_LIBRARIES zdll ${protobuf_SOURCE_DIR}) + else (ZLIB) + set(HAVE_ZLIB 0) + endif (ZLIB) +else (MSVC) + find_package(ZLIB) + if (ZLIB_FOUND) + set(HAVE_ZLIB 1) + else (ZLIB_FOUND) + set(HAVE_ZLIB 0) + # Explicitly set these to empty (override NOT_FOUND) so cmake doesn't + # complain when we use them later. + set(ZLIB_INCLUDE_DIRECTORIES) + set(ZLIB_LIBRARIES) + endif (ZLIB_FOUND) +endif (MSVC) + +if (HAVE_ZLIB) + add_definitions(-DHAVE_ZLIB) +endif (HAVE_ZLIB) + +if (MSVC) + if (BUILD_SHARED_LIBS) + add_definitions(-DPROTOBUF_USE_DLLS) + endif (BUILD_SHARED_LIBS) + add_definitions(/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305) +endif (MSVC) + +if (MSVC) + string(REPLACE "/" "\\" PROTOBUF_SOURCE_WIN32_PATH ${protobuf_SOURCE_DIR}) + string(REPLACE "/" "\\" PROTOBUF_BINARY_WIN32_PATH ${protobuf_BINARY_DIR}) + configure_file(extract_includes.bat.in extract_includes.bat) +endif (MSVC) + +get_filename_component(protobuf_source_dir ${protobuf_SOURCE_DIR} PATH) + +include_directories( + ${ZLIB_INCLUDE_DIRECTORIES} + ${protobuf_BINARY_DIR} + ${protobuf_source_dir}/src) + +if (MSVC) + # Add the "lib" prefix for generated .lib outputs. + set(LIB_PREFIX lib) +else (MSVC) + # When building with "make", "lib" prefix will be added automatically by + # the build tool. + set(LIB_PREFIX) +endif (MSVC) + +include(libprotobuf-lite.cmake) +include(libprotobuf.cmake) +include(libprotoc.cmake) +include(protoc.cmake) +if (BUILD_TESTING) + include(tests.cmake) +endif (BUILD_TESTING) diff --git a/cmake/README.md b/cmake/README.md new file mode 100644 index 00000000..c68defd8 --- /dev/null +++ b/cmake/README.md @@ -0,0 +1,139 @@ +This directory contains cmake files that can be used to generate MSVC project +files in order to build protobuf on windows. You need to have cmake installed +on your computer before proceeding. + +Compiling and Installing +======================== + +1. Check whether a gmock directory exists in the upper level directory. If you + checkout the code from github via "git clone", this gmock directory won't + exist and you won't be able to build protobuf unit-tests. Consider using one + of the release tar balls instead: + + https://github.com/google/protobuf/releases + + These release tar balls are more stable versions of protobuf and already + have the gmock directory included. + + You can also download gmock by yourself and put it in the right place. + + If you absolutely don't want to build and run protobuf unit-tests, skip + this step and use protobuf at your own risk. + +2. Use cmake to generate MSVC project files. Running the following commands + in a command shell will generate project files for Visual Studio 2008 in + a sub-directory named "build". + + $ cd path/to/protobuf/cmake + $ mkdir build + $ cd build + $ cmake -G "Visual Studio 9 2008" .. + + If you don't have gmock, skip the build of tests by turning off the + BUILD_TESTING option: + + $ cmake -G "Visual Studio 9 2008" -DBUILD_TESTING=OFF .. + +3. Open the generated protobuf.sln file in Microsoft Visual Studio. +4. Choose "Debug" or "Release" configuration as desired. +5. From the Build menu, choose "Build Solution". Wait for compiling to finish. +6. If you have built tests, run tests.exe and lite-test.exe from a command + shell and check that all tests pass. Make sure you have changed the working + directory to the output directory because tests.exe will try to find and run + test_plugin.exe in the working directory. +7. Run extract_includes.bat to copy all the public headers into a separate + "include" directory. This batch script can be found along with the generated + protobuf.sln file in the same directory. +8. Copy the contents of the include directory to wherever you want to put + headers. +9. Copy protoc.exe wherever you put build tools (probably somewhere in your + PATH). +10. Copy libprotobuf.lib, libprotobuf-lite.lib, and libprotoc.lib wherever you + put libraries. + + To avoid conflicts between the MSVC debug and release runtime libraries, when + compiling a debug build of your application, you may need to link against a + debug build of libprotobuf.lib. Similarly, release builds should link against + release libs. + +DLLs vs. static linking +======================= + +Static linking is now the default for the Protocol Buffer libraries. Due to +issues with Win32's use of a separate heap for each DLL, as well as binary +compatibility issues between different versions of MSVC's STL library, it is +recommended that you use static linkage only. However, it is possible to +build libprotobuf and libprotoc as DLLs if you really want. To do this, +do the following: + + 1. Add an additional flag "-DBUILD_SHARED_LIBS=ON" when invoking cmake: + + $ cmake -G "Visual Studio 9 2008" -DBUILD_SHARED_LIBS=ON .. + + 2. Follow the same steps as described in the above section. + 3. When compiling your project, make sure to #define PROTOBUF_USE_DLLS. + +When distributing your software to end users, we strongly recommend that you +do NOT install libprotobuf.dll or libprotoc.dll to any shared location. +Instead, keep these libraries next to your binaries, in your application's +own install directory. C++ makes it very difficult to maintain binary +compatibility between releases, so it is likely that future versions of these +libraries will *not* be usable as drop-in replacements. + +If your project is itself a DLL intended for use by third-party software, we +recommend that you do NOT expose protocol buffer objects in your library's +public interface, and that you statically link protocol buffers into your +library. + +ZLib support +============ + +If you want to include GzipInputStream and GzipOutputStream +(google/protobuf/io/gzip_stream.h) in libprotobuf, you will need to do a few +additional steps: + +1. Obtain a copy of the zlib library. The pre-compiled DLL at zlib.net works. +2. Make sure zlib's two headers are in your include path and that the .lib file + is in your library path. You could place all three files directly into this + cmake directory to compile libprotobuf, but they need to be visible to + your own project as well, so you should probably just put them into the + VC shared icnlude and library directories. +3. Add flag "-DZLIB=ON" when invoking cmake: + + $ cmake -G "Visual Studio 9 2008" -DZLIB=ON .. + + If it reports NOTFOUND for zlib_include or zlib_lib, you might haven't put + the headers or the .lib file in the right directory. +4) Open the generated protobuf.sln file and build as usual. + +Notes on Compiler Warnings +========================== + +The following warnings have been disabled while building the protobuf libraries +and compiler. You may have to disable some of them in your own project as +well, or live with them. + +* C4018 - 'expression' : signed/unsigned mismatch +* C4146 - unary minus operator applied to unsigned type, result still unsigned +* C4244 - Conversion from 'type1' to 'type2', possible loss of data. +* C4251 - 'identifier' : class 'type' needs to have dll-interface to be used by + clients of class 'type2' +* C4267 - Conversion from 'size_t' to 'type', possible loss of data. +* C4305 - 'identifier' : truncation from 'type1' to 'type2' +* C4355 - 'this' : used in base member initializer list +* C4800 - 'type' : forcing value to bool 'true' or 'false' (performance warning) +* C4996 - 'function': was declared deprecated + +C4251 is of particular note, if you are compiling the Protocol Buffer library +as a DLL (see previous section). The protocol buffer library uses templates in +its public interfaces. MSVC does not provide any reasonable way to export +template classes from a DLL. However, in practice, it appears that exporting +templates is not necessary anyway. Since the complete definition of any +template is available in the header files, anyone importing the DLL will just +end up compiling instances of the templates into their own binary. The +Protocol Buffer implementation does not rely on static template members being +unique, so there should be no problem with this, but MSVC prints warning +nevertheless. So, we disable it. Unfortunately, this warning will also be +produced when compiling code which merely uses protocol buffers, meaning you +may have to disable it in your code too. + diff --git a/cmake/extract_includes.bat.in b/cmake/extract_includes.bat.in new file mode 100644 index 00000000..4e34d81a --- /dev/null +++ b/cmake/extract_includes.bat.in @@ -0,0 +1,111 @@ +mkdir include +mkdir include\google +mkdir include\google\protobuf +mkdir include\google\protobuf\compiler +mkdir include\google\protobuf\compiler\cpp +mkdir include\google\protobuf\compiler\csharp +mkdir include\google\protobuf\compiler\java +mkdir include\google\protobuf\compiler\javanano +mkdir include\google\protobuf\compiler\objectivec +mkdir include\google\protobuf\compiler\python +mkdir include\google\protobuf\compiler\ruby +mkdir include\google\protobuf\io +mkdir include\google\protobuf\stubs +mkdir include\google\protobuf\util +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\any.h include\google\protobuf\any.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\any.pb.h include\google\protobuf\any.pb.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\api.pb.h include\google\protobuf\api.pb.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arena.h include\google\protobuf\arena.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arenastring.h include\google\protobuf\arenastring.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\code_generator.h include\google\protobuf\compiler\code_generator.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\command_line_interface.h include\google\protobuf\compiler\command_line_interface.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\cpp_generator.h include\google\protobuf\compiler\cpp\cpp_generator.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_generator.h include\google\protobuf\compiler\csharp\csharp_generator.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\importer.h include\google\protobuf\compiler\importer.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_generator.h include\google\protobuf\compiler\java\java_generator.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_names.h include\google\protobuf\compiler\java\java_names.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\javanano\javanano_generator.h include\google\protobuf\compiler\javanano\javanano_generator.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\objectivec\objectivec_generator.h include\google\protobuf\compiler\objectivec\objectivec_generator.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\objectivec\objectivec_helpers.h include\google\protobuf\compiler\objectivec\objectivec_helpers.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\parser.h include\google\protobuf\compiler\parser.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.h include\google\protobuf\compiler\plugin.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.pb.h include\google\protobuf\compiler\plugin.pb.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\python\python_generator.h include\google\protobuf\compiler\python\python_generator.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\ruby\ruby_generator.h include\google\protobuf\compiler\ruby\ruby_generator.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor.h include\google\protobuf\descriptor.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor.pb.h include\google\protobuf\descriptor.pb.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor_database.h include\google\protobuf\descriptor_database.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\duration.pb.h include\google\protobuf\duration.pb.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\dynamic_message.h include\google\protobuf\dynamic_message.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\empty.pb.h include\google\protobuf\empty.pb.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\extension_set.h include\google\protobuf\extension_set.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\field_mask.pb.h include\google\protobuf\field_mask.pb.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_enum_reflection.h include\google\protobuf\generated_enum_reflection.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_enum_util.h include\google\protobuf\generated_enum_util.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_reflection.h include\google\protobuf\generated_message_reflection.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_util.h include\google\protobuf\generated_message_util.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\coded_stream.h include\google\protobuf\io\coded_stream.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\gzip_stream.h include\google\protobuf\io\gzip_stream.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\printer.h include\google\protobuf\io\printer.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\strtod.h include\google\protobuf\io\strtod.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\tokenizer.h include\google\protobuf\io\tokenizer.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\zero_copy_stream.h include\google\protobuf\io\zero_copy_stream.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\zero_copy_stream_impl.h include\google\protobuf\io\zero_copy_stream_impl.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\zero_copy_stream_impl_lite.h include\google\protobuf\io\zero_copy_stream_impl_lite.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map.h include\google\protobuf\map.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_entry.h include\google\protobuf\map_entry.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_entry_lite.h include\google\protobuf\map_entry_lite.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_field.h include\google\protobuf\map_field.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_field_inl.h include\google\protobuf\map_field_inl.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_field_lite.h include\google\protobuf\map_field_lite.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_type_handler.h include\google\protobuf\map_type_handler.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\message.h include\google\protobuf\message.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\message_lite.h include\google\protobuf\message_lite.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\metadata.h include\google\protobuf\metadata.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection.h include\google\protobuf\reflection.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection_ops.h include\google\protobuf\reflection_ops.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\repeated_field.h include\google\protobuf\repeated_field.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\repeated_field_reflection.h include\google\protobuf\repeated_field_reflection.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\service.h include\google\protobuf\service.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\source_context.pb.h include\google\protobuf\source_context.pb.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\struct.pb.h include\google\protobuf\struct.pb.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomic_sequence_num.h include\google\protobuf\stubs\atomic_sequence_num.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops.h include\google\protobuf\stubs\atomicops.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_aix.h include\google\protobuf\stubs\atomicops_internals_aix.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_arm64_gcc.h include\google\protobuf\stubs\atomicops_internals_arm64_gcc.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_arm_gcc.h include\google\protobuf\stubs\atomicops_internals_arm_gcc.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_arm_qnx.h include\google\protobuf\stubs\atomicops_internals_arm_qnx.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_atomicword_compat.h include\google\protobuf\stubs\atomicops_internals_atomicword_compat.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_generic_gcc.h include\google\protobuf\stubs\atomicops_internals_generic_gcc.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_macosx.h include\google\protobuf\stubs\atomicops_internals_macosx.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_mips_gcc.h include\google\protobuf\stubs\atomicops_internals_mips_gcc.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_pnacl.h include\google\protobuf\stubs\atomicops_internals_pnacl.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_solaris.h include\google\protobuf\stubs\atomicops_internals_solaris.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_tsan.h include\google\protobuf\stubs\atomicops_internals_tsan.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_x86_gcc.h include\google\protobuf\stubs\atomicops_internals_x86_gcc.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_x86_msvc.h include\google\protobuf\stubs\atomicops_internals_x86_msvc.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\casts.h include\google\protobuf\stubs\casts.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\common.h include\google\protobuf\stubs\common.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\fastmem.h include\google\protobuf\stubs\fastmem.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\hash.h include\google\protobuf\stubs\hash.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\once.h include\google\protobuf\stubs\once.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\pbconfig.h include\google\protobuf\stubs\pbconfig.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\platform_macros.h include\google\protobuf\stubs\platform_macros.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\shared_ptr.h include\google\protobuf\stubs\shared_ptr.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\singleton.h include\google\protobuf\stubs\singleton.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\stl_util.h include\google\protobuf\stubs\stl_util.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\template_util.h include\google\protobuf\stubs\template_util.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\type_traits.h include\google\protobuf\stubs\type_traits.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\text_format.h include\google\protobuf\text_format.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\timestamp.pb.h include\google\protobuf\timestamp.pb.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\type.pb.h include\google\protobuf\type.pb.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\unknown_field_set.h include\google\protobuf\unknown_field_set.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\field_comparator.h include\google\protobuf\util\field_comparator.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\json_util.h include\google\protobuf\util\json_util.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\message_differencer.h include\google\protobuf\util\message_differencer.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\type_resolver.h include\google\protobuf\util\type_resolver.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\type_resolver_util.h include\google\protobuf\util\type_resolver_util.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format.h include\google\protobuf\wire_format.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format_lite.h include\google\protobuf\wire_format_lite.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format_lite_inl.h include\google\protobuf\wire_format_lite_inl.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wrappers.pb.h include\google\protobuf\wrappers.pb.h diff --git a/cmake/libprotobuf-lite.cmake b/cmake/libprotobuf-lite.cmake new file mode 100644 index 00000000..db55ea92 --- /dev/null +++ b/cmake/libprotobuf-lite.cmake @@ -0,0 +1,29 @@ +set(libprotobuf_lite_files + ${protobuf_source_dir}/src/google/protobuf/arena.cc + ${protobuf_source_dir}/src/google/protobuf/arenastring.cc + ${protobuf_source_dir}/src/google/protobuf/extension_set.cc + ${protobuf_source_dir}/src/google/protobuf/generated_message_util.cc + ${protobuf_source_dir}/src/google/protobuf/io/coded_stream.cc + ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream.cc + ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl_lite.cc + ${protobuf_source_dir}/src/google/protobuf/message_lite.cc + ${protobuf_source_dir}/src/google/protobuf/repeated_field.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/bytestream.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/common.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/once.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/status.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/statusor.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/stringpiece.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/stringprintf.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/strutil.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/time.cc + ${protobuf_source_dir}/src/google/protobuf/wire_format_lite.cc +) + +add_library(libprotobuf-lite ${libprotobuf_lite_files}) +target_link_libraries(libprotobuf-lite ${CMAKE_THREAD_LIBS_INIT}) +set_target_properties(libprotobuf-lite PROPERTIES + COMPILE_DEFINITIONS LIBPROTOBUF_EXPORTS + OUTPUT_NAME ${LIB_PREFIX}protobuf-lite) diff --git a/cmake/libprotobuf.cmake b/cmake/libprotobuf.cmake new file mode 100644 index 00000000..53ba3d3e --- /dev/null +++ b/cmake/libprotobuf.cmake @@ -0,0 +1,59 @@ +set(libprotobuf_files + ${protobuf_source_dir}/src/google/protobuf/any.cc + ${protobuf_source_dir}/src/google/protobuf/any.pb.cc + ${protobuf_source_dir}/src/google/protobuf/api.pb.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/importer.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/parser.cc + ${protobuf_source_dir}/src/google/protobuf/descriptor.cc + ${protobuf_source_dir}/src/google/protobuf/descriptor.pb.cc + ${protobuf_source_dir}/src/google/protobuf/descriptor_database.cc + ${protobuf_source_dir}/src/google/protobuf/duration.pb.cc + ${protobuf_source_dir}/src/google/protobuf/dynamic_message.cc + ${protobuf_source_dir}/src/google/protobuf/empty.pb.cc + ${protobuf_source_dir}/src/google/protobuf/extension_set_heavy.cc + ${protobuf_source_dir}/src/google/protobuf/field_mask.pb.cc + ${protobuf_source_dir}/src/google/protobuf/generated_message_reflection.cc + ${protobuf_source_dir}/src/google/protobuf/io/gzip_stream.cc + ${protobuf_source_dir}/src/google/protobuf/io/printer.cc + ${protobuf_source_dir}/src/google/protobuf/io/strtod.cc + ${protobuf_source_dir}/src/google/protobuf/io/tokenizer.cc + ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl.cc + ${protobuf_source_dir}/src/google/protobuf/map_field.cc + ${protobuf_source_dir}/src/google/protobuf/message.cc + ${protobuf_source_dir}/src/google/protobuf/reflection_ops.cc + ${protobuf_source_dir}/src/google/protobuf/service.cc + ${protobuf_source_dir}/src/google/protobuf/source_context.pb.cc + ${protobuf_source_dir}/src/google/protobuf/struct.pb.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/mathlimits.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/structurally_valid.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/substitute.cc + ${protobuf_source_dir}/src/google/protobuf/text_format.cc + ${protobuf_source_dir}/src/google/protobuf/timestamp.pb.cc + ${protobuf_source_dir}/src/google/protobuf/type.pb.cc + ${protobuf_source_dir}/src/google/protobuf/unknown_field_set.cc + ${protobuf_source_dir}/src/google/protobuf/util/field_comparator.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/datapiece.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/default_value_objectwriter.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/error_listener.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/field_mask_utility.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/json_escaping.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/json_objectwriter.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/json_stream_parser.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/object_writer.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/protostream_objectsource.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/protostream_objectwriter.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/type_info.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/type_info_test_helper.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/utility.cc + ${protobuf_source_dir}/src/google/protobuf/util/json_util.cc + ${protobuf_source_dir}/src/google/protobuf/util/message_differencer.cc + ${protobuf_source_dir}/src/google/protobuf/util/type_resolver_util.cc + ${protobuf_source_dir}/src/google/protobuf/wire_format.cc + ${protobuf_source_dir}/src/google/protobuf/wrappers.pb.cc +) + +add_library(libprotobuf ${libprotobuf_lite_files} ${libprotobuf_files}) +target_link_libraries(libprotobuf ${CMAKE_THREAD_LIBS_INIT} ${ZLIB_LIBRARIES}) +set_target_properties(libprotobuf PROPERTIES + COMPILE_DEFINITIONS LIBPROTOBUF_EXPORTS + OUTPUT_NAME ${LIB_PREFIX}protobuf) diff --git a/cmake/libprotoc.cmake b/cmake/libprotoc.cmake new file mode 100644 index 00000000..8caa9e9e --- /dev/null +++ b/cmake/libprotoc.cmake @@ -0,0 +1,95 @@ +set(libprotoc_files + ${protobuf_source_dir}/src/google/protobuf/compiler/code_generator.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/command_line_interface.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_enum.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_enum_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_extension.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_file.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_generator.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_helpers.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_map_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_service.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_string_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_enum.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_enum_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_extension.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_field_base.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_generator.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_helpers.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_message.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_message_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_writer.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_context.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_doc_comment.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_enum.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_enum_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_enum_field_lite.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_extension.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_file.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_generator.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_generator_factory.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_helpers.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_lazy_message_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_map_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_map_field_lite.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message_builder.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message_builder_lite.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message_field_lite.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message_lite.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_name_resolver.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_primitive_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_primitive_field_lite.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_service.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_shared_code_generator.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_string_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_string_field_lite.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_enum.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_enum_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_extension.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_file.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_generator.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_helpers.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_map_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_message.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_message_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_enum.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_extension.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_file.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_generator.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_message.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/plugin.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/plugin.pb.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/python/python_generator.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/ruby/ruby_generator.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/subprocess.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/zip_writer.cc +) + +add_library(libprotoc ${libprotoc_files}) +target_link_libraries(libprotoc libprotobuf) +set_target_properties(libprotoc PROPERTIES + COMPILE_DEFINITIONS LIBPROTOC_EXPORTS + OUTPUT_NAME ${LIB_PREFIX}protoc) diff --git a/cmake/protoc.cmake b/cmake/protoc.cmake new file mode 100644 index 00000000..4f07c389 --- /dev/null +++ b/cmake/protoc.cmake @@ -0,0 +1,6 @@ +set(protoc_files + ${protobuf_source_dir}/src/google/protobuf/compiler/main.cc +) + +add_executable(protoc ${protoc_files}) +target_link_libraries(protoc libprotobuf libprotoc) diff --git a/cmake/tests.cmake b/cmake/tests.cmake new file mode 100644 index 00000000..16c94933 --- /dev/null +++ b/cmake/tests.cmake @@ -0,0 +1,182 @@ +if (NOT EXISTS "${PROJECT_SOURCE_DIR}/../gmock/CMakeLists.txt") + message(FATAL_ERROR "Cannot find gmock directory.") +endif() + +include_directories( + ${protobuf_source_dir}/gmock + ${protobuf_source_dir}/gmock/gtest + ${protobuf_source_dir}/gmock/gtest/include + ${protobuf_source_dir}/gmock/include +) + +add_library(gmock STATIC + ${protobuf_source_dir}/gmock/src/gmock-all.cc + ${protobuf_source_dir}/gmock/gtest/src/gtest-all.cc +) +add_library(gmock_main STATIC ${protobuf_source_dir}/gmock/src/gmock_main.cc) +target_link_libraries(gmock_main gmock) + +set(lite_test_protos + google/protobuf/map_lite_unittest.proto + google/protobuf/unittest_import_lite.proto + google/protobuf/unittest_import_public_lite.proto + google/protobuf/unittest_lite.proto +) + +set(tests_protos + google/protobuf/any_test.proto + google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto + google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto + google/protobuf/map_proto2_unittest.proto + google/protobuf/map_unittest.proto + google/protobuf/unittest.proto + google/protobuf/unittest_arena.proto + google/protobuf/unittest_custom_options.proto + google/protobuf/unittest_drop_unknown_fields.proto + google/protobuf/unittest_embed_optimize_for.proto + google/protobuf/unittest_empty.proto + google/protobuf/unittest_enormous_descriptor.proto + google/protobuf/unittest_import.proto + google/protobuf/unittest_import_public.proto + google/protobuf/unittest_lite_imports_nonlite.proto + google/protobuf/unittest_mset.proto + google/protobuf/unittest_no_arena.proto + google/protobuf/unittest_no_arena_import.proto + google/protobuf/unittest_no_field_presence.proto + google/protobuf/unittest_no_generic_services.proto + google/protobuf/unittest_optimize_for.proto + google/protobuf/unittest_preserve_unknown_enum.proto + google/protobuf/unittest_preserve_unknown_enum2.proto + google/protobuf/unittest_proto3_arena.proto + google/protobuf/unittest_well_known_types.proto + google/protobuf/util/internal/testdata/anys.proto + google/protobuf/util/internal/testdata/books.proto + google/protobuf/util/internal/testdata/default_value.proto + google/protobuf/util/internal/testdata/default_value_test.proto + google/protobuf/util/internal/testdata/field_mask.proto + google/protobuf/util/internal/testdata/maps.proto + google/protobuf/util/internal/testdata/struct.proto + google/protobuf/util/internal/testdata/timestamp_duration.proto + google/protobuf/util/json_format_proto3.proto +) + +macro(compile_proto_file filename) + get_filename_component(dirname ${filename} PATH) + get_filename_component(basename ${filename} NAME_WE) + add_custom_command( + OUTPUT ${protobuf_source_dir}/src/${dirname}/${basename}.pb.cc + DEPENDS protoc ${protobuf_source_dir}/src/${dirname}/${basename}.proto + COMMAND protoc ${protobuf_source_dir}/src/${dirname}/${basename}.proto + --proto_path=${protobuf_source_dir}/src + --cpp_out=${protobuf_source_dir}/src + ) +endmacro(compile_proto_file) + +set(lite_test_proto_files) +foreach(proto_file ${lite_test_protos}) + compile_proto_file(${proto_file}) + string(REPLACE .proto .pb.cc pb_file ${proto_file}) + set(lite_test_proto_files ${lite_test_proto_files} + ${protobuf_source_dir}/src/${pb_file}) +endforeach(proto_file) + +set(tests_proto_files) +foreach(proto_file ${tests_protos}) + compile_proto_file(${proto_file}) + string(REPLACE .proto .pb.cc pb_file ${proto_file}) + set(tests_proto_files ${tests_proto_files} + ${protobuf_source_dir}/src/${pb_file}) +endforeach(proto_file) + +set(common_test_files + ${protobuf_source_dir}/src/google/protobuf/arena_test_util.cc + ${protobuf_source_dir}/src/google/protobuf/map_test_util.cc + ${protobuf_source_dir}/src/google/protobuf/test_util.cc + ${protobuf_source_dir}/src/google/protobuf/testing/file.cc + ${protobuf_source_dir}/src/google/protobuf/testing/googletest.cc +) + +set(tests_files + ${protobuf_source_dir}/src/google/protobuf/any_test.cc + ${protobuf_source_dir}/src/google/protobuf/arena_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/arenastring_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/command_line_interface_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/importer_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_plugin_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/mock_code_generator.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/parser_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/python/python_plugin_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/descriptor_database_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/descriptor_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/drop_unknown_fields_test.cc + ${protobuf_source_dir}/src/google/protobuf/dynamic_message_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/extension_set_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/generated_message_reflection_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/io/coded_stream_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/io/printer_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/io/tokenizer_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/map_field_test.cc + ${protobuf_source_dir}/src/google/protobuf/map_test.cc + ${protobuf_source_dir}/src/google/protobuf/message_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/no_field_presence_test.cc + ${protobuf_source_dir}/src/google/protobuf/preserve_unknown_enum_test.cc + ${protobuf_source_dir}/src/google/protobuf/proto3_arena_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/reflection_ops_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/repeated_field_reflection_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/repeated_field_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/bytestream_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/common_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/once_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/status_test.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/statusor_test.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/stringpiece_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/stringprintf_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/structurally_valid_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/strutil_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/template_util_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/time_test.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/type_traits_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/text_format_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/unknown_field_set_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/util/field_comparator_test.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/default_value_objectwriter_test.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/json_objectwriter_test.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/json_stream_parser_test.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/protostream_objectsource_test.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/protostream_objectwriter_test.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/type_info_test_helper.cc + ${protobuf_source_dir}/src/google/protobuf/util/json_util_test.cc + ${protobuf_source_dir}/src/google/protobuf/util/type_resolver_util_test.cc + ${protobuf_source_dir}/src/google/protobuf/well_known_types_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/wire_format_unittest.cc +) + +add_executable(tests ${tests_files} ${common_test_files} ${tests_proto_files} ${lite_test_proto_files}) +target_link_libraries(tests libprotoc libprotobuf gmock_main) + +set(test_plugin_files + ${protobuf_source_dir}/src/google/protobuf/compiler/mock_code_generator.cc + ${protobuf_source_dir}/src/google/protobuf/testing/file.cc + ${protobuf_source_dir}/src/google/protobuf/testing/file.h + ${protobuf_source_dir}/src/google/protobuf/compiler/test_plugin.cc +) + +add_executable(test_plugin ${test_plugin_files}) +target_link_libraries(test_plugin libprotoc libprotobuf gmock) + +set(lite_test_files + ${protobuf_source_dir}/src/google/protobuf/arena_test_util.cc + ${protobuf_source_dir}/src/google/protobuf/lite_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/map_lite_test_util.cc + ${protobuf_source_dir}/src/google/protobuf/test_util_lite.cc +) +add_executable(lite-test ${lite_test_files} ${lite_test_proto_files}) +target_link_libraries(lite-test libprotobuf-lite) diff --git a/config.h.include b/config.h.include deleted file mode 100644 index 0c557fbe..00000000 --- a/config.h.include +++ /dev/null @@ -1,7 +0,0 @@ -HASH_MAP_CLASS -HASH_MAP_H -HASH_NAMESPACE -HASH_SET_CLASS -HASH_SET_H -HAVE_HASH_MAP -HAVE_HASH_SET diff --git a/configure.ac b/configure.ac index 8018cc75..ef5342ce 100644 --- a/configure.ac +++ b/configure.ac @@ -17,6 +17,9 @@ AC_INIT([Protocol Buffers],[3.0.0-alpha-4-pre],[protobuf@googlegroups.com],[prot AM_MAINTAINER_MODE([enable]) AC_CONFIG_SRCDIR(src/google/protobuf/message.cc) +# The config file is generated but not used by the source code, since we only +# need very few of them, e.g. HAVE_PTHREAD and HAVE_ZLIB. Those macros are +# passed down in CXXFLAGS manually in src/Makefile.am AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) @@ -146,6 +149,9 @@ AS_IF([test "$with_protoc" != "no"], [ AM_CONDITIONAL([USE_EXTERNAL_PROTOC], [test "$with_protoc" != "no"]) ACX_PTHREAD +AM_CONDITIONAL([HAVE_PTHREAD], [test "x$acx_pthread_ok" = "xyes"]) + +# We still keep this for improving pbconfig.h for unsupported platforms. AC_CXX_STL_HASH case "$target_os" in @@ -157,12 +163,12 @@ case "$target_os" in ;; esac -# HACK: Make gtest's configure script pick up our copy of CFLAGS and CXXFLAGS, -# since the flags added by ACX_CHECK_SUNCC must be used when compiling gtest +# HACK: Make gmock's configure script pick up our copy of CFLAGS and CXXFLAGS, +# since the flags added by ACX_CHECK_SUNCC must be used when compiling gmock # too. export CFLAGS export CXXFLAGS -AC_CONFIG_SUBDIRS([gtest]) +AC_CONFIG_SUBDIRS([gmock]) AC_CONFIG_FILES([Makefile src/Makefile conformance/Makefile protobuf.pc protobuf-lite.pc]) AC_OUTPUT diff --git a/conformance/Makefile.am b/conformance/Makefile.am index 95343f14..cccbac9e 100644 --- a/conformance/Makefile.am +++ b/conformance/Makefile.am @@ -57,7 +57,7 @@ conformance-java: javac_middleman # Targets for actually running tests. test_cpp: protoc_middleman conformance-test-runner conformance-cpp - ./conformance-test-runner ./conformance-cpp + ./conformance-test-runner --failure_list failure_list_cpp.txt ./conformance-cpp test_java: protoc_middleman conformance-test-runner conformance-java ./conformance-test-runner ./conformance-java diff --git a/conformance/conformance_test.cc b/conformance/conformance_test.cc index 857f2152..7a7fc6f5 100644 --- a/conformance/conformance_test.cc +++ b/conformance/conformance_test.cc @@ -126,12 +126,11 @@ string submsg(uint32_t fn, const string& buf) { #define UNKNOWN_FIELD 666 -uint32_t GetFieldNumberForType(WireFormatLite::FieldType type, bool repeated) { +uint32_t GetFieldNumberForType(FieldDescriptor::Type type, bool repeated) { const Descriptor* d = TestAllTypes().GetDescriptor(); for (int i = 0; i < d->field_count(); i++) { const FieldDescriptor* f = d->field(i); - if (static_cast<WireFormatLite::FieldType>(f->type()) == type && - f->is_repeated() == repeated) { + if (f->type() == type && f->is_repeated() == repeated) { return f->number(); } } @@ -139,16 +138,37 @@ uint32_t GetFieldNumberForType(WireFormatLite::FieldType type, bool repeated) { return 0; } +string UpperCase(string str) { + for (int i = 0; i < str.size(); i++) { + str[i] = toupper(str[i]); + } + return str; +} + } // anonymous namespace namespace google { namespace protobuf { -void ConformanceTestSuite::ReportSuccess() { +void ConformanceTestSuite::ReportSuccess(const string& test_name) { + if (expected_to_fail_.erase(test_name) != 0) { + StringAppendF(&output_, + "ERROR: test %s is in the failure list, but test succeeded. " + "Remove it from the failure list.\n", + test_name.c_str()); + unexpected_succeeding_tests_.insert(test_name); + } successes_++; } -void ConformanceTestSuite::ReportFailure(const char *fmt, ...) { +void ConformanceTestSuite::ReportFailure(const string& test_name, + const char* fmt, ...) { + if (expected_to_fail_.erase(test_name) == 1) { + StringAppendF(&output_, "FAILED AS EXPECTED, test=%s: ", test_name.c_str()); + } else { + StringAppendF(&output_, "ERROR, test=%s: ", test_name.c_str()); + unexpected_failing_tests_.insert(test_name); + } va_list args; va_start(args, fmt); StringAppendV(&output_, fmt, args); @@ -156,8 +176,13 @@ void ConformanceTestSuite::ReportFailure(const char *fmt, ...) { failures_++; } -void ConformanceTestSuite::RunTest(const ConformanceRequest& request, +void ConformanceTestSuite::RunTest(const string& test_name, + const ConformanceRequest& request, ConformanceResponse* response) { + if (test_names_.insert(test_name).second == false) { + GOOGLE_LOG(FATAL) << "Duplicated test name: " << test_name; + } + string serialized_request; string serialized_response; request.SerializeToString(&serialized_request); @@ -170,14 +195,16 @@ void ConformanceTestSuite::RunTest(const ConformanceRequest& request, } if (verbose_) { - StringAppendF(&output_, "conformance test: request=%s, response=%s\n", + StringAppendF(&output_, "conformance test: name=%s, request=%s, response=%s\n", + test_name.c_str(), request.ShortDebugString().c_str(), response->ShortDebugString().c_str()); } } -void ConformanceTestSuite::DoExpectParseFailureForProto(const string& proto, - int line) { +// Expect that this precise protobuf will cause a parse error. +void ConformanceTestSuite::ExpectParseFailureForProto( + const string& proto, const string& test_name) { ConformanceRequest request; ConformanceResponse response; request.set_protobuf_payload(proto); @@ -186,31 +213,29 @@ void ConformanceTestSuite::DoExpectParseFailureForProto(const string& proto, // we let it send its response as this. We must not leave it unspecified. request.set_requested_output(ConformanceRequest::PROTOBUF); - RunTest(request, &response); + RunTest(test_name, request, &response); if (response.result_case() == ConformanceResponse::kParseError) { - ReportSuccess(); + ReportSuccess(test_name); } else { - ReportFailure("Should have failed, but didn't. Line: %d, Request: %s, " + ReportFailure(test_name, + "Should have failed to parse, but didn't. Request: %s, " "response: %s\n", - line, request.ShortDebugString().c_str(), response.ShortDebugString().c_str()); } } -// Expect that this precise protobuf will cause a parse error. -#define ExpectParseFailureForProto(proto) DoExpectParseFailureForProto(proto, __LINE__) - // Expect that this protobuf will cause a parse error, even if it is followed // by valid protobuf data. We can try running this twice: once with this // data verbatim and once with this data followed by some valid data. // // TODO(haberman): implement the second of these. -#define ExpectHardParseFailureForProto(proto) DoExpectParseFailureForProto(proto, __LINE__) - +void ConformanceTestSuite::ExpectHardParseFailureForProto( + const string& proto, const string& test_name) { + return ExpectParseFailureForProto(proto, test_name); +} -void ConformanceTestSuite::TestPrematureEOFForType( - WireFormatLite::FieldType type) { +void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) { // Incomplete values for each wire type. static const string incompletes[6] = { string("\x80"), // VARINT @@ -223,45 +248,51 @@ void ConformanceTestSuite::TestPrematureEOFForType( uint32_t fieldnum = GetFieldNumberForType(type, false); uint32_t rep_fieldnum = GetFieldNumberForType(type, true); - WireFormatLite::WireType wire_type = - WireFormatLite::WireTypeForFieldType(type); + WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( + static_cast<WireFormatLite::FieldType>(type)); const string& incomplete = incompletes[wire_type]; + const string type_name = + UpperCase(string(".") + FieldDescriptor::TypeName(type)); - // EOF before a known non-repeated value. - ExpectParseFailureForProto(tag(fieldnum, wire_type)); + ExpectParseFailureForProto( + tag(fieldnum, wire_type), + "PrematureEofBeforeKnownNonRepeatedValue" + type_name); - // EOF before a known repeated value. - ExpectParseFailureForProto(tag(rep_fieldnum, wire_type)); + ExpectParseFailureForProto( + tag(rep_fieldnum, wire_type), + "PrematureEofBeforeKnownRepeatedValue" + type_name); - // EOF before an unknown value. - ExpectParseFailureForProto(tag(UNKNOWN_FIELD, wire_type)); + ExpectParseFailureForProto( + tag(UNKNOWN_FIELD, wire_type), + "PrematureEofBeforeUnknownValue" + type_name); - // EOF inside a known non-repeated value. ExpectParseFailureForProto( - cat( tag(fieldnum, wire_type), incomplete )); + cat( tag(fieldnum, wire_type), incomplete ), + "PrematureEofInsideKnownNonRepeatedValue" + type_name); - // EOF inside a known repeated value. ExpectParseFailureForProto( - cat( tag(rep_fieldnum, wire_type), incomplete )); + cat( tag(rep_fieldnum, wire_type), incomplete ), + "PrematureEofInsideKnownRepeatedValue" + type_name); - // EOF inside an unknown value. ExpectParseFailureForProto( - cat( tag(UNKNOWN_FIELD, wire_type), incomplete )); + cat( tag(UNKNOWN_FIELD, wire_type), incomplete ), + "PrematureEofInsideUnknownValue" + type_name); if (wire_type == WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { - // EOF in the middle of delimited data for known non-repeated value. ExpectParseFailureForProto( - cat( tag(fieldnum, wire_type), varint(1) )); + cat( tag(fieldnum, wire_type), varint(1) ), + "PrematureEofInDelimitedDataForKnownNonRepeatedValue" + type_name); - // EOF in the middle of delimited data for known repeated value. ExpectParseFailureForProto( - cat( tag(rep_fieldnum, wire_type), varint(1) )); + cat( tag(rep_fieldnum, wire_type), varint(1) ), + "PrematureEofInDelimitedDataForKnownRepeatedValue" + type_name); // EOF in the middle of delimited data for unknown value. ExpectParseFailureForProto( - cat( tag(UNKNOWN_FIELD, wire_type), varint(1) )); + cat( tag(UNKNOWN_FIELD, wire_type), varint(1) ), + "PrematureEofInDelimitedDataForUnknownValue" + type_name); - if (type == WireFormatLite::TYPE_MESSAGE) { + if (type == FieldDescriptor::TYPE_MESSAGE) { // Submessage ends in the middle of a value. string incomplete_submsg = cat( tag(WireFormatLite::TYPE_INT32, WireFormatLite::WIRETYPE_VARINT), @@ -269,42 +300,86 @@ void ConformanceTestSuite::TestPrematureEOFForType( ExpectHardParseFailureForProto( cat( tag(fieldnum, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), varint(incomplete_submsg.size()), - incomplete_submsg )); + incomplete_submsg ), + "PrematureEofInSubmessageValue" + type_name); } - } else if (type != WireFormatLite::TYPE_GROUP) { + } else if (type != FieldDescriptor::TYPE_GROUP) { // Non-delimited, non-group: eligible for packing. // Packed region ends in the middle of a value. ExpectHardParseFailureForProto( cat( tag(rep_fieldnum, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), varint(incomplete.size()), - incomplete )); + incomplete ), + "PrematureEofInPackedFieldValue" + type_name); // EOF in the middle of packed region. ExpectParseFailureForProto( cat( tag(rep_fieldnum, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - varint(1) )); + varint(1) ), + "PrematureEofInPackedField" + type_name); } } -void ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, +void ConformanceTestSuite::SetFailureList(const vector<string>& failure_list) { + expected_to_fail_.clear(); + std::copy(failure_list.begin(), failure_list.end(), + std::inserter(expected_to_fail_, expected_to_fail_.end())); +} + +bool ConformanceTestSuite::CheckSetEmpty(const set<string>& set_to_check, + const char* msg) { + if (set_to_check.empty()) { + return true; + } else { + StringAppendF(&output_, "\n"); + StringAppendF(&output_, "ERROR: %s:\n", msg); + for (set<string>::const_iterator iter = set_to_check.begin(); + iter != set_to_check.end(); ++iter) { + StringAppendF(&output_, "%s\n", iter->c_str()); + } + return false; + } +} + +bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, std::string* output) { runner_ = runner; output_.clear(); successes_ = 0; failures_ = 0; + test_names_.clear(); + unexpected_failing_tests_.clear(); + unexpected_succeeding_tests_.clear(); for (int i = 1; i <= FieldDescriptor::MAX_TYPE; i++) { if (i == FieldDescriptor::TYPE_GROUP) continue; - TestPrematureEOFForType(static_cast<WireFormatLite::FieldType>(i)); + TestPrematureEOFForType(static_cast<FieldDescriptor::Type>(i)); } + StringAppendF(&output_, "\n"); StringAppendF(&output_, "CONFORMANCE SUITE FINISHED: completed %d tests, %d successes, " "%d failures.\n", successes_ + failures_, successes_, failures_); + bool ok = + CheckSetEmpty(expected_to_fail_, + "These tests were listed in the failure list, but they " + "don't exist. Remove them from the failure list") && + + CheckSetEmpty(unexpected_failing_tests_, + "These tests failed. If they can't be fixed right now, " + "you can add them to the failure list so the overall " + "suite can succeed") && + + CheckSetEmpty(unexpected_succeeding_tests_, + "These tests succeeded, even though they were listed in " + "the failure list. Remove them from the failure list"); + output->assign(output_); + + return ok; } } // namespace protobuf diff --git a/conformance/conformance_test.h b/conformance/conformance_test.h index c16f9c0b..764a8d33 100644 --- a/conformance/conformance_test.h +++ b/conformance/conformance_test.h @@ -83,24 +83,50 @@ class ConformanceTestSuite { public: ConformanceTestSuite() : verbose_(false) {} + // Sets the list of tests that are expected to fail when RunSuite() is called. + // RunSuite() will fail unless the set of failing tests is exactly the same + // as this list. + void SetFailureList(const std::vector<std::string>& failure_list); + // Run all the conformance tests against the given test runner. // Test output will be stored in "output". - void RunSuite(ConformanceTestRunner* runner, std::string* output); + // + // Returns true if the set of failing tests was exactly the same as the + // failure list. If SetFailureList() was not called, returns true if all + // tests passed. + bool RunSuite(ConformanceTestRunner* runner, std::string* output); private: - void ReportSuccess(); - void ReportFailure(const char* fmt, ...); - void RunTest(const conformance::ConformanceRequest& request, + void ReportSuccess(const std::string& test_name); + void ReportFailure(const std::string& test_name, const char* fmt, ...); + void RunTest(const std::string& test_name, + const conformance::ConformanceRequest& request, conformance::ConformanceResponse* response); - void DoExpectParseFailureForProto(const std::string& proto, int line); - void TestPrematureEOFForType( - google::protobuf::internal::WireFormatLite::FieldType type); - + void ExpectParseFailureForProto(const std::string& proto, + const std::string& test_name); + void ExpectHardParseFailureForProto(const std::string& proto, + const std::string& test_name); + void TestPrematureEOFForType(google::protobuf::FieldDescriptor::Type type); + bool CheckSetEmpty(const set<string>& set_to_check, const char* msg); ConformanceTestRunner* runner_; int successes_; int failures_; bool verbose_; std::string output_; + + // The set of test names that are expected to fail in this run, but haven't + // failed yet. + std::set<std::string> expected_to_fail_; + + // The set of test names that have been run. Used to ensure that there are no + // duplicate names in the suite. + std::set<std::string> test_names_; + + // The set of tests that failed, but weren't expected to. + std::set<std::string> unexpected_failing_tests_; + + // The set of tests that succeeded, but weren't expected to. + std::set<std::string> unexpected_succeeding_tests_; }; } // namespace protobuf diff --git a/conformance/conformance_test_runner.cc b/conformance/conformance_test_runner.cc index e0bb50a5..b56e19cf 100644 --- a/conformance/conformance_test_runner.cc +++ b/conformance/conformance_test_runner.cc @@ -55,6 +55,8 @@ #include <errno.h> #include <unistd.h> +#include <fstream> +#include <vector> #include "conformance.pb.h" #include "conformance_test.h" @@ -62,6 +64,8 @@ using conformance::ConformanceRequest; using conformance::ConformanceResponse; using google::protobuf::internal::scoped_array; +using std::string; +using std::vector; #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) @@ -180,18 +184,67 @@ class ForkPipeRunner : public google::protobuf::ConformanceTestRunner { std::string executable_; }; +void UsageError() { + fprintf(stderr, + "Usage: conformance-test-runner [options] <test-program>\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, + " --failure_list <filename> Use to specify list of tests\n"); + fprintf(stderr, + " that are expected to fail. File\n"); + fprintf(stderr, + " should contain one test name per\n"); + fprintf(stderr, + " line. Use '#' for comments.\n"); + exit(1); +} + +void ParseFailureList(const char *filename, vector<string>* failure_list) { + std::ifstream infile(filename); + for (string line; getline(infile, line);) { + // Remove whitespace. + line.erase(std::remove_if(line.begin(), line.end(), ::isspace), + line.end()); + + // Remove comments. + line = line.substr(0, line.find("#")); + + if (!line.empty()) { + failure_list->push_back(line); + } + } +} int main(int argc, char *argv[]) { - if (argc < 2) { - fprintf(stderr, "Usage: conformance-test-runner <test-program>\n"); - exit(1); + int arg = 1; + char *program; + vector<string> failure_list; + + for (int arg = 1; arg < argc; ++arg) { + if (strcmp(argv[arg], "--failure_list") == 0) { + if (++arg == argc) UsageError(); + ParseFailureList(argv[arg], &failure_list); + } else if (argv[arg][0] == '-') { + fprintf(stderr, "Unknown option: %s\n", argv[arg]); + UsageError(); + } else { + if (arg != argc - 1) { + fprintf(stderr, "Too many arguments.\n"); + UsageError(); + } + program = argv[arg]; + } } - ForkPipeRunner runner(argv[1]); + ForkPipeRunner runner(program); google::protobuf::ConformanceTestSuite suite; + suite.SetFailureList(failure_list); std::string output; - suite.RunSuite(&runner, &output); + bool ok = suite.RunSuite(&runner, &output); fwrite(output.c_str(), 1, output.size(), stderr); + + return ok ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/conformance/failure_list_cpp.txt b/conformance/failure_list_cpp.txt new file mode 100644 index 00000000..d792eddd --- /dev/null +++ b/conformance/failure_list_cpp.txt @@ -0,0 +1,21 @@ +# This is the list of conformance tests that are known to fail for the C++ +# implementation right now. These should be fixed. +# +# By listing them here we can keep tabs on which ones are failing and be sure +# that we don't introduce regressions in other tests. +# +# TODO(haberman): insert links to corresponding bugs tracking the issue. +# Should we use GitHub issues or the Google-internal bug tracker? + +PrematureEofBeforeKnownRepeatedValue.MESSAGE +PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE +PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE +PrematureEofInPackedField.BOOL +PrematureEofInPackedField.ENUM +PrematureEofInPackedField.INT32 +PrematureEofInPackedField.INT64 +PrematureEofInPackedField.SINT32 +PrematureEofInPackedField.SINT64 +PrematureEofInPackedField.UINT32 +PrematureEofInPackedField.UINT64 +PrematureEofInsideKnownRepeatedValue.MESSAGE diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/Unittest.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/Unittest.cs index 4dda7bcd..d3441937 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/Unittest.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/Unittest.cs @@ -6432,7 +6432,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasOneofNestedMessage { - get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage OneofNestedMessage { get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage) result.oneofField_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.DefaultInstance; } @@ -22008,7 +22008,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooMessage { - get { return result.fooCase_ == FooOneofCase.FooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes FooMessage { get { return result.fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypes) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance; } @@ -22050,7 +22050,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooGroup { - get { return result.fooCase_ == FooOneofCase.FooGroup; } + get { return result.fooCase_ == FooOneofCase.FooGroup; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup FooGroup { get { return result.fooCase_ == FooOneofCase.FooGroup ? (global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.DefaultInstance; } @@ -24405,7 +24405,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooMessage { - get { return result.fooCase_ == FooOneofCase.FooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage FooMessage { get { return result.fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } @@ -24447,7 +24447,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooGroup { - get { return result.fooCase_ == FooOneofCase.FooGroup; } + get { return result.fooCase_ == FooOneofCase.FooGroup; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup FooGroup { get { return result.fooCase_ == FooOneofCase.FooGroup ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.DefaultInstance; } @@ -24489,7 +24489,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooLazyMessage { - get { return result.fooCase_ == FooOneofCase.FooLazyMessage; } + get { return result.fooCase_ == FooOneofCase.FooLazyMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage FooLazyMessage { get { return result.fooCase_ == FooOneofCase.FooLazyMessage ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } @@ -25377,7 +25377,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooMessage { - get { return result.fooCase_ == FooOneofCase.FooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage FooMessage { get { return result.fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.DefaultInstance; } diff --git a/csharp/src/ProtocolBuffersLite.Test/TestProtos/Unittest.cs b/csharp/src/ProtocolBuffersLite.Test/TestProtos/Unittest.cs index 4dda7bcd..d3441937 100644 --- a/csharp/src/ProtocolBuffersLite.Test/TestProtos/Unittest.cs +++ b/csharp/src/ProtocolBuffersLite.Test/TestProtos/Unittest.cs @@ -6432,7 +6432,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasOneofNestedMessage { - get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage OneofNestedMessage { get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage) result.oneofField_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.DefaultInstance; } @@ -22008,7 +22008,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooMessage { - get { return result.fooCase_ == FooOneofCase.FooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes FooMessage { get { return result.fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypes) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance; } @@ -22050,7 +22050,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooGroup { - get { return result.fooCase_ == FooOneofCase.FooGroup; } + get { return result.fooCase_ == FooOneofCase.FooGroup; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup FooGroup { get { return result.fooCase_ == FooOneofCase.FooGroup ? (global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.DefaultInstance; } @@ -24405,7 +24405,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooMessage { - get { return result.fooCase_ == FooOneofCase.FooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage FooMessage { get { return result.fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } @@ -24447,7 +24447,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooGroup { - get { return result.fooCase_ == FooOneofCase.FooGroup; } + get { return result.fooCase_ == FooOneofCase.FooGroup; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup FooGroup { get { return result.fooCase_ == FooOneofCase.FooGroup ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.DefaultInstance; } @@ -24489,7 +24489,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooLazyMessage { - get { return result.fooCase_ == FooOneofCase.FooLazyMessage; } + get { return result.fooCase_ == FooOneofCase.FooLazyMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage FooLazyMessage { get { return result.fooCase_ == FooOneofCase.FooLazyMessage ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } @@ -25377,7 +25377,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooMessage { - get { return result.fooCase_ == FooOneofCase.FooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage FooMessage { get { return result.fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.DefaultInstance; } diff --git a/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestLite.cs b/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestLite.cs index d84a505f..bf0da956 100644 --- a/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestLite.cs +++ b/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestLite.cs @@ -6440,7 +6440,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasOneofNestedMessage { - get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage OneofNestedMessage { get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage) result.oneofField_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage.DefaultInstance; } diff --git a/gmock.BUILD b/gmock.BUILD new file mode 100644 index 00000000..66cddea9 --- /dev/null +++ b/gmock.BUILD @@ -0,0 +1,23 @@ +cc_library( + name = "gtest", + srcs = [ + "gmock-1.7.0/gtest/src/gtest-all.cc", + "gmock-1.7.0/src/gmock-all.cc", + ], + includes = [ + "gmock-1.7.0", + "gmock-1.7.0/gtest", + "gmock-1.7.0/gtest/include", + "gmock-1.7.0/include", + ], + linkopts = ["-pthread"], + visibility = ["//visibility:public"], +) + +cc_library( + name = "gtest_main", + srcs = ["gmock-1.7.0/src/gmock_main.cc"], + linkopts = ["-pthread"], + visibility = ["//visibility:public"], + deps = [":gtest"], +) 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 b1b0c53a..322ada8e 100644 --- a/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java +++ b/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java @@ -33,6 +33,7 @@ package com.google.protobuf.nano; import java.io.IOException; import java.nio.BufferOverflowException; import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.nio.ReadOnlyBufferException; /** @@ -61,6 +62,7 @@ public final class CodedOutputByteBufferNano { private CodedOutputByteBufferNano(final ByteBuffer buffer) { this.buffer = buffer; + this.buffer.order(ByteOrder.LITTLE_ENDIAN); } /** @@ -1038,24 +1040,20 @@ public final class CodedOutputByteBufferNano { /** Write a little-endian 32-bit integer. */ public void writeRawLittleEndian32(final int value) throws IOException { - writeRawByte((value ) & 0xFF); - writeRawByte((value >> 8) & 0xFF); - writeRawByte((value >> 16) & 0xFF); - writeRawByte((value >> 24) & 0xFF); + if (buffer.remaining() < 4) { + throw new OutOfSpaceException(buffer.position(), buffer.limit()); + } + buffer.putInt(value); } public static final int LITTLE_ENDIAN_32_SIZE = 4; /** Write a little-endian 64-bit integer. */ public void writeRawLittleEndian64(final long value) throws IOException { - writeRawByte((int)(value ) & 0xFF); - writeRawByte((int)(value >> 8) & 0xFF); - writeRawByte((int)(value >> 16) & 0xFF); - writeRawByte((int)(value >> 24) & 0xFF); - writeRawByte((int)(value >> 32) & 0xFF); - writeRawByte((int)(value >> 40) & 0xFF); - writeRawByte((int)(value >> 48) & 0xFF); - writeRawByte((int)(value >> 56) & 0xFF); + if (buffer.remaining() < 8) { + throw new OutOfSpaceException(buffer.position(), buffer.limit()); + } + buffer.putLong(value); } public static final int LITTLE_ENDIAN_64_SIZE = 8; diff --git a/objectivec/DevTools/compile_testing_protos.sh b/objectivec/DevTools/compile_testing_protos.sh new file mode 100755 index 00000000..f414bd87 --- /dev/null +++ b/objectivec/DevTools/compile_testing_protos.sh @@ -0,0 +1,113 @@ +#!/bin/bash + +# Invoked by the Xcode projects to build the protos needed for the unittests. + +set -eu + +readonly OUTPUT_DIR="${PROJECT_DERIVED_FILE_DIR}/protos" + +# Helper for bailing. +die() { + echo "Error: $1" + exit 2 +} + +# What to do. +case "${ACTION}" in + "") + # Build, fall thru + ;; + "clean") + rm -rf "${OUTPUT_DIR}" + exit 0 + ;; + *) + die "Unknown action requested: ${ACTION}" + ;; +esac + +# Move to the top of the protobuf directories. +cd "${SRCROOT}/.." + +[[ -x src/protoc ]] || \ + die "Could not find the protoc binary; make sure you have built it (objectivec/DevTools/full_mac_build.sh -h)." + +RUN_PROTOC=no +if [[ ! -d "${OUTPUT_DIR}" ]] ; then + RUN_PROTOC=yes +else + # Find the newest input file (protos, compiler, and this script). + # (these patterns catch some extra stuff, but better to over sample than + # under) + readonly NewestInput=$(find \ + src/google/protobuf/*.proto \ + objectivec/Tests/*.proto \ + src/.libs src/*.la src/protoc \ + objectivec/DevTools/compile_testing_protos.sh \ + -type f -print0 \ + | xargs -0 stat -f "%m %N" \ + | sort -n | tail -n1 | cut -f2- -d" ") + # Find the oldest output file. + readonly OldestOutput=$(find \ + "${OUTPUT_DIR}" \ + -type f -print0 \ + | xargs -0 stat -f "%m %N" \ + | sort -n -r | tail -n1 | cut -f2- -d" ") + # If the newest input is newer than the oldest output, regenerate. + if [[ "${NewestInput}" -nt "${OldestOutput}" ]] ; then + RUN_PROTOC=yes + fi +fi + +if [[ "${RUN_PROTOC}" != "yes" ]] ; then + # Up to date. + exit 0 +fi + +# Ensure the output dir exists +mkdir -p "${OUTPUT_DIR}/google/protobuf" + +CORE_PROTO_FILES=( \ + src/google/protobuf/unittest_custom_options.proto \ + src/google/protobuf/unittest_enormous_descriptor.proto \ + src/google/protobuf/unittest_embed_optimize_for.proto \ + src/google/protobuf/unittest_empty.proto \ + src/google/protobuf/unittest_import.proto \ + src/google/protobuf/unittest_import_lite.proto \ + src/google/protobuf/unittest_lite.proto \ + src/google/protobuf/unittest_mset.proto \ + src/google/protobuf/unittest_no_generic_services.proto \ + src/google/protobuf/unittest_optimize_for.proto \ + src/google/protobuf/unittest.proto \ + src/google/protobuf/unittest_import_public.proto \ + src/google/protobuf/unittest_import_public_lite.proto \ + src/google/protobuf/unittest_drop_unknown_fields.proto \ + src/google/protobuf/unittest_preserve_unknown_enum.proto \ + src/google/protobuf/map_lite_unittest.proto \ + src/google/protobuf/map_proto2_unittest.proto \ + src/google/protobuf/map_unittest.proto \ +) + +compile_proto() { + src/protoc \ + --objc_out="${OUTPUT_DIR}/google/protobuf" \ + --proto_path=src/google/protobuf/ \ + --proto_path=src \ + $* +} + +for a_proto in "${CORE_PROTO_FILES[@]}" ; do + compile_proto "${a_proto}" +done + +OBJC_PROTO_FILES=( \ + objectivec/Tests/unittest_cycle.proto \ + objectivec/Tests/unittest_runtime_proto2.proto \ + objectivec/Tests/unittest_runtime_proto3.proto \ + objectivec/Tests/unittest_objc.proto \ + objectivec/Tests/unittest_objc_startup.proto \ +) + +for a_proto in "${OBJC_PROTO_FILES[@]}" ; do + compile_proto --proto_path="objectivec/Tests" "${a_proto}" +done diff --git a/objectivec/DevTools/full_mac_build.sh b/objectivec/DevTools/full_mac_build.sh index 57c4f438..2192b760 100755 --- a/objectivec/DevTools/full_mac_build.sh +++ b/objectivec/DevTools/full_mac_build.sh @@ -162,7 +162,7 @@ wrapped_make -j "${NUM_MAKE_JOBS}" all wrapped_make -j "${NUM_MAKE_JOBS}" check header "Ensuring the ObjC descriptors are current." -# Find the newest input file (protos, compiler, and this script). +# Find the newest input file (protos, compiler, and the generator script). # (these patterns catch some extra stuff, but better to over sample than under) readonly NewestInput=$(find \ src/google/protobuf/*.proto \ diff --git a/objectivec/GPBArray.h b/objectivec/GPBArray.h index 3fcba7af..8c6396a9 100644 --- a/objectivec/GPBArray.h +++ b/objectivec/GPBArray.h @@ -30,13 +30,15 @@ #import <Foundation/Foundation.h> -#import "GPBTypes.h" +#import "GPBRuntimeTypes.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. +NS_ASSUME_NONNULL_BEGIN + //%PDDM-EXPAND DECLARE_ARRAYS() // This block of code is generated, do not edit it directly. @@ -321,21 +323,21 @@ @property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + (instancetype)array; -+ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func; -+ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func ++ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func; ++ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func rawValue:(int32_t)value; + (instancetype)arrayWithValueArray:(GPBEnumArray *)array; -+ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func ++ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func capacity:(NSUInteger)count; -- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func; +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; // Initializes the array, copying the values. -- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func rawValues:(const int32_t [])values count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; - (instancetype)initWithValueArray:(GPBEnumArray *)array; -- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func capacity:(NSUInteger)count; // These will return kGPBUnrecognizedEnumeratorValue if the value at index is not a @@ -392,6 +394,8 @@ //%PDDM-EXPAND-END DECLARE_ARRAYS() +NS_ASSUME_NONNULL_END + //%PDDM-DEFINE DECLARE_ARRAYS() //%ARRAY_INTERFACE_SIMPLE(Int32, int32_t) //%ARRAY_INTERFACE_SIMPLE(UInt32, uint32_t) @@ -444,21 +448,21 @@ //%@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; //% //%+ (instancetype)array; -//%+ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func; -//%+ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func +//%+ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func; +//%+ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func //% rawValue:(TYPE)value; //%+ (instancetype)arrayWithValueArray:(GPB##NAME##Array *)array; -//%+ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func +//%+ (instancetype)arrayWithValidationFunction:(nullable GPBEnumValidationFunc)func //% capacity:(NSUInteger)count; //% -//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func; +//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; //% //%// Initializes the array, copying the values. -//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func +//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func //% rawValues:(const TYPE [])values //% count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; //%- (instancetype)initWithValueArray:(GPB##NAME##Array *)array; -//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func +//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func //% capacity:(NSUInteger)count; //% //%// These will return kGPBUnrecognizedEnumeratorValue if the value at index is not a diff --git a/objectivec/GPBCodedInputStream.h b/objectivec/GPBCodedInputStream.h index e9b27e22..42a04941 100644 --- a/objectivec/GPBCodedInputStream.h +++ b/objectivec/GPBCodedInputStream.h @@ -33,6 +33,8 @@ @class GPBMessage; @class GPBExtensionRegistry; +NS_ASSUME_NONNULL_BEGIN + // Reads and decodes protocol message fields. // Subclassing of GPBCodedInputStream is NOT supported. @interface GPBCodedInputStream : NSObject @@ -60,11 +62,11 @@ - (int64_t)readSInt64; - (BOOL)readBool; - (NSString *)readString; -- (NSData *)readData; +- (NSData *)readBytes; // Read an embedded message field value from the stream. - (void)readMessage:(GPBMessage *)message - extensionRegistry:(GPBExtensionRegistry *)extensionRegistry; + extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry; // Reads and discards a single field, given its tag value. Returns NO if the // tag is an endgroup tag, in which case nothing is skipped. Otherwise, @@ -81,3 +83,5 @@ - (void)checkLastTagWas:(int32_t)value; @end + +NS_ASSUME_NONNULL_END diff --git a/objectivec/GPBCodedInputStream.m b/objectivec/GPBCodedInputStream.m index 79d31fc7..71758baa 100644 --- a/objectivec/GPBCodedInputStream.m +++ b/objectivec/GPBCodedInputStream.m @@ -38,7 +38,7 @@ static const NSUInteger kDefaultRecursionLimit = 64; -static inline void CheckSize(GPBCodedInputStreamState *state, size_t size) { +static void CheckSize(GPBCodedInputStreamState *state, size_t size) { size_t newSize = state->bufferPos + size; if (newSize > state->bufferSize) { [NSException raise:NSParseErrorException format:@""]; @@ -50,26 +50,26 @@ static inline void CheckSize(GPBCodedInputStreamState *state, size_t size) { } } -static inline int8_t ReadRawByte(GPBCodedInputStreamState *state) { +static int8_t ReadRawByte(GPBCodedInputStreamState *state) { CheckSize(state, sizeof(int8_t)); return ((int8_t *)state->bytes)[state->bufferPos++]; } -static inline int32_t ReadRawLittleEndian32(GPBCodedInputStreamState *state) { +static 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) { +static 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) { +static int32_t ReadRawVarint32(GPBCodedInputStreamState *state) { int8_t tmp = ReadRawByte(state); if (tmp >= 0) { return tmp; @@ -104,7 +104,7 @@ static inline int32_t ReadRawVarint32(GPBCodedInputStreamState *state) { return result; } -static inline int64_t ReadRawVarint64(GPBCodedInputStreamState *state) { +static int64_t ReadRawVarint64(GPBCodedInputStreamState *state) { int32_t shift = 0; int64_t result = 0; while (shift < 64) { @@ -119,7 +119,7 @@ static inline int64_t ReadRawVarint64(GPBCodedInputStreamState *state) { return 0; } -static inline void SkipRawData(GPBCodedInputStreamState *state, size_t size) { +static void SkipRawData(GPBCodedInputStreamState *state, size_t size) { CheckSize(state, size); state->bufferPos += size; } @@ -222,7 +222,7 @@ NSString *GPBCodedInputStreamReadRetainedString( return result; } -NSData *GPBCodedInputStreamReadRetainedData(GPBCodedInputStreamState *state) { +NSData *GPBCodedInputStreamReadRetainedBytes(GPBCodedInputStreamState *state) { int32_t size = ReadRawVarint32(state); if (size < 0) return nil; CheckSize(state, size); @@ -232,7 +232,7 @@ NSData *GPBCodedInputStreamReadRetainedData(GPBCodedInputStreamState *state) { return result; } -NSData *GPBCodedInputStreamReadRetainedDataNoCopy( +NSData *GPBCodedInputStreamReadRetainedBytesNoCopy( GPBCodedInputStreamState *state) { int32_t size = ReadRawVarint32(state); if (size < 0) return nil; @@ -453,8 +453,8 @@ void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, GPBCodedInputStreamPopLimit(&state_, oldLimit); } -- (NSData *)readData { - return [GPBCodedInputStreamReadRetainedData(&state_) autorelease]; +- (NSData *)readBytes { + return [GPBCodedInputStreamReadRetainedBytes(&state_) autorelease]; } - (uint32_t)readUInt32 { @@ -499,7 +499,7 @@ void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, // 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) { +static bool AreBytesIn7BitASCII(const uint8_t *bytes, NSUInteger len) { // In the loops below, it's more efficient to collect rather than do // conditional at every step. #if __LP64__ @@ -587,7 +587,7 @@ static inline bool AreBytesIn7BitASCII(const uint8_t *bytes, NSUInteger len) { return true; } -static inline void GPBStringInitStringValue(GPBString *string) { +static void GPBStringInitStringValue(GPBString *string) { OSSpinLockLock(&string->lock_); GPBStringInitStringValueAlreadyLocked(string); OSSpinLockUnlock(&string->lock_); diff --git a/objectivec/GPBCodedInputStream_PackagePrivate.h b/objectivec/GPBCodedInputStream_PackagePrivate.h index ba6471ef..e482b4c9 100644 --- a/objectivec/GPBCodedInputStream_PackagePrivate.h +++ b/objectivec/GPBCodedInputStream_PackagePrivate.h @@ -114,9 +114,9 @@ int64_t GPBCodedInputStreamReadSInt64(GPBCodedInputStreamState *state); BOOL GPBCodedInputStreamReadBool(GPBCodedInputStreamState *state); NSString *GPBCodedInputStreamReadRetainedString(GPBCodedInputStreamState *state) __attribute((ns_returns_retained)); -NSData *GPBCodedInputStreamReadRetainedData(GPBCodedInputStreamState *state) +NSData *GPBCodedInputStreamReadRetainedBytes(GPBCodedInputStreamState *state) __attribute((ns_returns_retained)); -NSData *GPBCodedInputStreamReadRetainedDataNoCopy( +NSData *GPBCodedInputStreamReadRetainedBytesNoCopy( GPBCodedInputStreamState *state) __attribute((ns_returns_retained)); size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, diff --git a/objectivec/GPBCodedOutputStream.h b/objectivec/GPBCodedOutputStream.h index 1f1eb38a..a5aef170 100644 --- a/objectivec/GPBCodedOutputStream.h +++ b/objectivec/GPBCodedOutputStream.h @@ -30,7 +30,7 @@ #import <Foundation/Foundation.h> -#import "GPBTypes.h" +#import "GPBRuntimeTypes.h" #import "GPBWireFormat.h" @class GPBBoolArray; @@ -44,6 +44,8 @@ @class GPBUInt64Array; @class GPBUnknownFieldSet; +NS_ASSUME_NONNULL_BEGIN + @interface GPBCodedOutputStream : NSObject // Creates a new stream to write into data. Data must be sized to fit or it @@ -53,12 +55,10 @@ + (instancetype)streamWithOutputStream:(NSOutputStream *)output bufferSize:(size_t)bufferSize; -- (instancetype)initWithOutputStream:(NSOutputStream *)output; - (instancetype)initWithData:(NSMutableData *)data; +- (instancetype)initWithOutputStream:(NSOutputStream *)output; - (instancetype)initWithOutputStream:(NSOutputStream *)output bufferSize:(size_t)bufferSize; -- (instancetype)initWithOutputStream:(NSOutputStream *)output - data:(NSMutableData *)data; - (void)flush; @@ -84,110 +84,110 @@ // 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)writeDoubleArray:(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)writeFloatArray:(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)writeUInt64Array:(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)writeInt64Array:(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)writeInt32Array:(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)writeUInt32Array:(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)writeFixed64Array:(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)writeFixed32Array:(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)writeSInt32Array:(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)writeSInt64Array:(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)writeSFixed64Array:(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)writeSFixed32Array:(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)writeBoolArray:(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)writeEnumArray:(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)writeStringArray:(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)writeMessageArray:(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)writeBytes:(int32_t)fieldNumber value:(NSData *)value; +- (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray *)values; +- (void)writeBytesNoTag:(NSData *)value; - (void)writeGroup:(int32_t)fieldNumber value:(GPBMessage *)value; -- (void)writeGroups:(int32_t)fieldNumber values:(NSArray *)values; +- (void)writeGroupArray:(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)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray *)values; - (void)writeUnknownGroupNoTag:(int32_t)fieldNumber value:(GPBUnknownFieldSet *)value; @@ -230,7 +230,7 @@ size_t GPBComputeUnknownGroupSize(int32_t fieldNumber, __attribute__((const)); size_t GPBComputeMessageSize(int32_t fieldNumber, GPBMessage *value) __attribute__((const)); -size_t GPBComputeDataSize(int32_t fieldNumber, NSData *value) +size_t GPBComputeBytesSize(int32_t fieldNumber, NSData *value) __attribute__((const)); size_t GPBComputeUInt32Size(int32_t fieldNumber, uint32_t value) __attribute__((const)); @@ -243,7 +243,7 @@ size_t GPBComputeSInt32Size(int32_t fieldNumber, int32_t value) 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) +size_t GPBComputeWireFormatTagSize(int field_number, GPBDataType dataType) __attribute__((const)); size_t GPBComputeDoubleSizeNoTag(double value) __attribute__((const)); @@ -259,7 +259,7 @@ 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 GPBComputeBytesSizeNoTag(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)); @@ -294,25 +294,27 @@ size_t GPBComputeEnumSize(int32_t fieldNumber, int32_t value) CF_EXTERN_C_END +NS_ASSUME_NONNULL_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##Array:(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##Array:(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##Array:(int32_t)fieldNumber values:(NSArray *)values; //%- (void)write##NAME##NoTag:(int32_t)fieldNumber //% NAME$S value:(TYPE)value; //% @@ -335,6 +337,6 @@ CF_EXTERN_C_END //%_WRITE_PACKABLE_DECLS(Enum, Enum, int32_t) //%_WRITE_UNPACKABLE_DECLS(String, NSString *) //%_WRITE_UNPACKABLE_DECLS(Message, GPBMessage *) -//%_WRITE_UNPACKABLE_DECLS(Data, NSData *) +//%_WRITE_UNPACKABLE_DECLS(Bytes, NSData *) //%_WRITE_GROUP_DECLS(Group, GPBMessage *) //%_WRITE_GROUP_DECLS(UnknownGroup, GPBUnknownFieldSet *) diff --git a/objectivec/GPBCodedOutputStream.m b/objectivec/GPBCodedOutputStream.m index 9604c128..70142e6f 100644 --- a/objectivec/GPBCodedOutputStream.m +++ b/objectivec/GPBCodedOutputStream.m @@ -184,6 +184,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, return [self initWithOutputStream:output data:data]; } +// This initializer isn't exposed, but it is the designated initializer. +// Setting OutputStream and NSData is to control the buffering behavior/size +// of the work, but that is more obvious via the bufferSize: version. - (instancetype)initWithOutputStream:(NSOutputStream *)output data:(NSMutableData *)data { if ((self = [super init])) { @@ -372,14 +375,14 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, [self writeMessageNoTag:value]; } -- (void)writeDataNoTag:(NSData *)value { +- (void)writeBytesNoTag:(NSData *)value { GPBWriteRawVarint32(&state_, (int32_t)[value length]); [self writeRawData:value]; } -- (void)writeData:(int32_t)fieldNumber value:(NSData *)value { +- (void)writeBytes:(int32_t)fieldNumber value:(NSData *)value { GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatLengthDelimited); - [self writeDataNoTag:value]; + [self writeBytesNoTag:value]; } - (void)writeUInt32NoTag:(uint32_t)value { @@ -436,9 +439,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, } //%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 { +//%- (void)write##NAME##Array:(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; @@ -461,7 +464,7 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%} //% //%PDDM-DEFINE WRITE_UNPACKABLE_DEFNS(NAME, TYPE) -//%- (void)write##NAME##s:(int32_t)fieldNumber values:(NSArray *)values { +//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray *)values { //% for (TYPE *value in values) { //% [self write##NAME:fieldNumber value:value]; //% } @@ -470,9 +473,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%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 { +- (void)writeDoubleArray:(int32_t)fieldNumber + values:(GPBDoubleArray *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -497,9 +500,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%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 { +- (void)writeFloatArray:(int32_t)fieldNumber + values:(GPBFloatArray *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -524,9 +527,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%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 { +- (void)writeUInt64Array:(int32_t)fieldNumber + values:(GPBUInt64Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -551,9 +554,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%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 { +- (void)writeInt64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -578,9 +581,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%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 { +- (void)writeInt32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -605,9 +608,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%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 { +- (void)writeUInt32Array:(int32_t)fieldNumber + values:(GPBUInt32Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -632,9 +635,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%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 { +- (void)writeFixed64Array:(int32_t)fieldNumber + values:(GPBUInt64Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -659,9 +662,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%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 { +- (void)writeFixed32Array:(int32_t)fieldNumber + values:(GPBUInt32Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -686,9 +689,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%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 { +- (void)writeSInt32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -713,9 +716,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%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 { +- (void)writeSInt64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -740,9 +743,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%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 { +- (void)writeSFixed64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -767,9 +770,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%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 { +- (void)writeSFixed32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -794,9 +797,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%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 { +- (void)writeBoolArray:(int32_t)fieldNumber + values:(GPBBoolArray *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -821,9 +824,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%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 { +- (void)writeEnumArray:(int32_t)fieldNumber + values:(GPBEnumArray *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -848,7 +851,7 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%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 { +- (void)writeStringArray:(int32_t)fieldNumber values:(NSArray *)values { for (NSString *value in values) { [self writeString:fieldNumber value:value]; } @@ -857,25 +860,25 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%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 { +- (void)writeMessageArray:(int32_t)fieldNumber values:(NSArray *)values { for (GPBMessage *value in values) { [self writeMessage:fieldNumber value:value]; } } -//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Data, NSData) +//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Bytes, NSData) // This block of code is generated, do not edit it directly. -- (void)writeDatas:(int32_t)fieldNumber values:(NSArray *)values { +- (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray *)values { for (NSData *value in values) { - [self writeData:fieldNumber value:value]; + [self writeBytes: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 { +- (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray *)values { for (GPBMessage *value in values) { [self writeGroup:fieldNumber value:value]; } @@ -884,7 +887,7 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%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 { +- (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray *)values { for (GPBUnknownFieldSet *value in values) { [self writeUnknownGroup:fieldNumber value:value]; } @@ -906,7 +909,7 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem, GPBWireFormatStartGroup); GPBWriteUInt32(&state_, GPBWireFormatMessageSetTypeId, fieldNumber); - [self writeData:GPBWireFormatMessageSetMessage value:value]; + [self writeBytes:GPBWireFormatMessageSetMessage value:value]; GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem, GPBWireFormatEndGroup); } @@ -1062,7 +1065,7 @@ size_t GPBComputeMessageSizeNoTag(GPBMessage *value) { return GPBComputeRawVarint32SizeForInteger(size) + size; } -size_t GPBComputeDataSizeNoTag(NSData *value) { +size_t GPBComputeBytesSizeNoTag(NSData *value) { NSUInteger valueLength = [value length]; return GPBComputeRawVarint32SizeForInteger(valueLength) + valueLength; } @@ -1143,8 +1146,8 @@ 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 GPBComputeBytesSize(int32_t fieldNumber, NSData *value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeBytesSizeNoTag(value); } size_t GPBComputeUInt32Size(int32_t fieldNumber, uint32_t value) { @@ -1183,7 +1186,7 @@ size_t GPBComputeRawMessageSetExtensionSize(int32_t fieldNumber, NSData *value) { return GPBComputeTagSize(GPBWireFormatMessageSetItem) * 2 + GPBComputeUInt32Size(GPBWireFormatMessageSetTypeId, fieldNumber) + - GPBComputeDataSize(GPBWireFormatMessageSetMessage, value); + GPBComputeBytesSize(GPBWireFormatMessageSetMessage, value); } size_t GPBComputeTagSize(int32_t fieldNumber) { @@ -1191,9 +1194,9 @@ size_t GPBComputeTagSize(int32_t fieldNumber) { GPBWireFormatMakeTag(fieldNumber, GPBWireFormatVarint)); } -size_t GPBComputeWireFormatTagSize(int field_number, GPBType type) { +size_t GPBComputeWireFormatTagSize(int field_number, GPBDataType dataType) { size_t result = GPBComputeTagSize(field_number); - if (type == GPBTypeGroup) { + if (dataType == GPBDataTypeGroup) { // Groups have both a start and an end tag. return result * 2; } else { diff --git a/objectivec/GPBDescriptor.h b/objectivec/GPBDescriptor.h index 97b46b3c..360afe96 100644 --- a/objectivec/GPBDescriptor.h +++ b/objectivec/GPBDescriptor.h @@ -30,7 +30,7 @@ #import <Foundation/Foundation.h> -#import "GPBTypes.h" +#import "GPBRuntimeTypes.h" @class GPBEnumDescriptor; @class GPBFieldDescriptor; @@ -38,6 +38,8 @@ @class GPBFileDescriptor; @class GPBOneofDescriptor; +NS_ASSUME_NONNULL_BEGIN + typedef NS_ENUM(NSInteger, GPBFileSyntax) { GPBFileSyntaxUnknown = 0, GPBFileSyntaxProto2 = 2, @@ -53,20 +55,20 @@ typedef NS_ENUM(NSInteger, GPBFieldType) { @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) const GPBExtensionRange *extensionRanges; +@property(nonatomic, readonly, strong, nullable) NSArray *fields; +@property(nonatomic, readonly, strong, nullable) NSArray *oneofs; +@property(nonatomic, readonly, strong, nullable) NSArray *enums; +@property(nonatomic, readonly, nullable) 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; +- (nullable GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber; +- (nullable GPBFieldDescriptor *)fieldWithName:(NSString *)name; +- (nullable GPBOneofDescriptor *)oneofWithName:(NSString *)name; +- (nullable GPBEnumDescriptor *)enumWithName:(NSString *)name; @end @@ -81,39 +83,39 @@ typedef NS_ENUM(NSInteger, GPBFieldType) { @property(nonatomic, readonly) NSString *name; @property(nonatomic, readonly) NSArray *fields; -- (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber; -- (GPBFieldDescriptor *)fieldWithName:(NSString *)name; +- (nullable GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber; +- (nullable 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) GPBDataType dataType; @property(nonatomic, readonly) BOOL hasDefaultValue; -@property(nonatomic, readonly) GPBValue defaultValue; +@property(nonatomic, readonly) GPBGenericValue 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) GPBDataType mapKeyDataType; @property(nonatomic, readonly, getter=isPackable) BOOL packable; -@property(nonatomic, readonly, assign) GPBOneofDescriptor *containingOneof; +@property(nonatomic, readonly, assign, nullable) GPBOneofDescriptor *containingOneof; -@property(nonatomic, readonly) GPBFieldOptions *fieldOptions; +@property(nonatomic, readonly, nullable) GPBFieldOptions *fieldOptions; // Message properties -@property(nonatomic, readonly, assign) Class msgClass; +@property(nonatomic, readonly, assign, nullable) Class msgClass; // Enum properties -@property(nonatomic, readonly, strong) GPBEnumDescriptor *enumDescriptor; +@property(nonatomic, readonly, strong, nullable) 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; +- (nullable NSString *)textFormatName; @end @@ -122,19 +124,23 @@ typedef NS_ENUM(NSInteger, GPBFieldType) { @property(nonatomic, readonly, copy) NSString *name; @property(nonatomic, readonly) GPBEnumValidationFunc enumVerifier; -- (NSString *)enumNameForValue:(int32_t)number; -- (BOOL)getValue:(int32_t *)outValue forEnumName:(NSString *)name; +- (nullable NSString *)enumNameForValue:(int32_t)number; +- (BOOL)getValue:(nullable int32_t *)outValue forEnumName:(NSString *)name; -- (NSString *)textFormatNameForValue:(int32_t)number; +- (nullable NSString *)textFormatNameForValue:(int32_t)number; @end -@interface GPBExtensionDescriptor : NSObject +@interface GPBExtensionDescriptor : NSObject<NSCopying> @property(nonatomic, readonly) uint32_t fieldNumber; -@property(nonatomic, readonly) GPBType type; +@property(nonatomic, readonly) Class containingMessageClass; +@property(nonatomic, readonly) GPBDataType dataType; @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; +@property(nonatomic, readonly, strong, nullable) GPBEnumDescriptor *enumDescriptor; +@property(nonatomic, readonly) id defaultValue; @end + +NS_ASSUME_NONNULL_END diff --git a/objectivec/GPBDescriptor.m b/objectivec/GPBDescriptor.m index b955018c..bae9187e 100644 --- a/objectivec/GPBDescriptor.m +++ b/objectivec/GPBDescriptor.m @@ -369,16 +369,26 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { GPBWireFormat format; if ((description->flags & GPBFieldMapKeyMask) != 0) { // Maps are repeated messages on the wire. - format = GPBWireFormatForType(GPBTypeMessage, NO); + format = GPBWireFormatForType(GPBDataTypeMessage, NO); } else { - format = GPBWireFormatForType(description->type, - description->flags & GPBFieldPacked); + format = GPBWireFormatForType(description->dataType, + ((description->flags & GPBFieldPacked) != 0)); } return GPBWireFormatMakeTag(description->number, format); } +uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) { + GPBMessageFieldDescription *description = self->description_; + NSCAssert((description->flags & GPBFieldRepeated) != 0, + @"Only valid on repeated fields"); + GPBWireFormat format = + GPBWireFormatForType(description->dataType, + ((description->flags & GPBFieldPacked) == 0)); + return GPBWireFormatMakeTag(description->number, format); +} + @implementation GPBFieldDescriptor { - GPBValue defaultValue_; + GPBGenericValue defaultValue_; GPBFieldOptions *fieldOptions_; // Message ivars @@ -416,12 +426,66 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { getSel_ = sel_getUid(description->name); setSel_ = SelFromStrings("set", description->name, NULL, YES); + GPBDataType dataType = description->dataType; + BOOL isMessage = GPBDataTypeIsMessage(dataType); + BOOL isMapOrArray = GPBFieldIsMapOrArray(self); + + if (isMapOrArray) { + // map<>/repeated fields get a *Count property (inplace of a has*) to + // support checking if there are any entries without triggering + // autocreation. + hasOrCountSel_ = SelFromStrings(NULL, description->name, "_Count", NO); + } else { + // If there is a positive hasIndex, then: + // - All fields types for proto2 messages get has* selectors. + // - Only message fields for proto3 messages get has* selectors. + // Note: the positive check is to handle oneOfs, we can't check + // containingOneof_ because it isn't set until after initialization. + if ((description->hasIndex >= 0) && + (description->hasIndex != GPBNoHasBit) && + ((syntax != GPBFileSyntaxProto3) || isMessage)) { + hasOrCountSel_ = SelFromStrings("has", description->name, NULL, NO); + setHasSel_ = SelFromStrings("setHas", description->name, NULL, YES); + } + } + + // Extra type specific data. + if (isMessage) { + const char *className = description->dataTypeSpecific.className; + msgClass_ = objc_getClass(className); + NSAssert(msgClass_, @"Class %s not defined", className); + } else if (dataType == GPBDataTypeEnum) { + if ((description_->flags & GPBFieldHasEnumDescriptor) != 0) { + enumHandling_.enumDescriptor_ = + description->dataTypeSpecific.enumDescFunc(); + } else { + enumHandling_.enumVerifier_ = + description->dataTypeSpecific.enumVerifier; + } + } + + // Non map<>/repeated fields can have defaults. + if (!isMapOrArray) { + defaultValue_ = description->defaultValue; + if (dataType == GPBDataTypeBytes) { + // Data stored as a length prefixed (network byte order) c-string in + // descriptor structure. + const uint8_t *bytes = (const uint8_t *)defaultValue_.valueData; + if (bytes) { + uint32_t length = *((uint32_t *)bytes); + length = ntohl(length); + bytes += sizeof(length); + defaultValue_.valueData = + [[NSData alloc] initWithBytes:bytes length:length]; + } + } + } + + // FieldOptions stored as a length prefixed (network byte order) c-escaped + // string in descriptor records. 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); @@ -434,69 +498,20 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { error:NULL] 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 && + if (description_->dataType == GPBDataTypeBytes && !(description_->flags & GPBFieldRepeated)) { [defaultValue_.valueData release]; } [super dealloc]; } -- (GPBType)type { - return description_->type; +- (GPBDataType)dataType { + return description_->dataType; } - (BOOL)hasDefaultValue { @@ -530,36 +545,36 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { } } -- (GPBType)mapKeyType { +- (GPBDataType)mapKeyDataType { switch (description_->flags & GPBFieldMapKeyMask) { case GPBFieldMapKeyInt32: - return GPBTypeInt32; + return GPBDataTypeInt32; case GPBFieldMapKeyInt64: - return GPBTypeInt64; + return GPBDataTypeInt64; case GPBFieldMapKeyUInt32: - return GPBTypeUInt32; + return GPBDataTypeUInt32; case GPBFieldMapKeyUInt64: - return GPBTypeUInt64; + return GPBDataTypeUInt64; case GPBFieldMapKeySInt32: - return GPBTypeSInt32; + return GPBDataTypeSInt32; case GPBFieldMapKeySInt64: - return GPBTypeSInt64; + return GPBDataTypeSInt64; case GPBFieldMapKeyFixed32: - return GPBTypeFixed32; + return GPBDataTypeFixed32; case GPBFieldMapKeyFixed64: - return GPBTypeFixed64; + return GPBDataTypeFixed64; case GPBFieldMapKeySFixed32: - return GPBTypeSFixed32; + return GPBDataTypeSFixed32; case GPBFieldMapKeySFixed64: - return GPBTypeSFixed64; + return GPBDataTypeSFixed64; case GPBFieldMapKeyBool: - return GPBTypeBool; + return GPBDataTypeBool; case GPBFieldMapKeyString: - return GPBTypeString; + return GPBDataTypeString; default: NSAssert(0, @"Not a map type"); - return GPBTypeInt32; // For lack of anything better. + return GPBDataTypeInt32; // For lack of anything better. } } @@ -568,8 +583,8 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { } - (BOOL)isValidEnumValue:(int32_t)value { - NSAssert(description_->type == GPBTypeEnum, - @"Field Must be of type GPBTypeEnum"); + NSAssert(description_->dataType == GPBDataTypeEnum, + @"Field Must be of type GPBDataTypeEnum"); if (description_->flags & GPBFieldHasEnumDescriptor) { return enumHandling_.enumDescriptor_.enumVerifier(value); } else { @@ -585,18 +600,18 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { } } -- (GPBValue)defaultValue { +- (GPBGenericValue)defaultValue { // Depends on the fact that defaultValue_ is initialized either to "0/nil" or // to an actual defaultValue in our initializer. - GPBValue value = defaultValue_; + GPBGenericValue 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) { + GPBDataType type = description_->dataType; + if (type == GPBDataTypeBytes && value.valueData == nil) { value.valueData = GPBEmptyNSData(); - } else if (type == GPBTypeString && value.valueString == nil) { + } else if (type == GPBDataTypeString && value.valueString == nil) { value.valueString = @""; } } @@ -635,7 +650,7 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { } // Groups vs. other fields. - if (description_->type == GPBTypeGroup) { + if (description_->dataType == GPBDataTypeGroup) { // Just capitalize the first letter. unichar firstChar = [name characterAtIndex:0]; if (firstChar >= 'a' && firstChar <= 'z') { @@ -811,16 +826,70 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { @end -@implementation GPBExtensionDescriptor +@implementation GPBExtensionDescriptor { + GPBGenericValue defaultValue_; +} + +@synthesize containingMessageClass = containingMessageClass_; - (instancetype)initWithExtensionDescription: (GPBExtensionDescription *)description { if ((self = [super init])) { description_ = description; + +#if DEBUG + const char *className = description->messageOrGroupClassName; + if (className) { + NSAssert(objc_lookUpClass(className) != Nil, + @"Class %s not defined", className); + } +#endif + + if (description->extendedClass) { + Class containingClass = objc_lookUpClass(description->extendedClass); + NSAssert(containingClass, @"Class %s not defined", + description->extendedClass); + containingMessageClass_ = containingClass; + } + + GPBDataType type = description_->dataType; + if (type == GPBDataTypeBytes) { + // 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 == GPBDataTypeMessage || type == GPBDataTypeGroup) { + // 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_->dataType == GPBDataTypeBytes) && + !GPBExtensionIsRepeated(description_)) { + [defaultValue_.valueData release]; + } + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { +#pragma unused(zone) + // Immutable. + return [self retain]; +} + - (NSString *)singletonName { return @(description_->singletonName); } @@ -833,12 +902,24 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { return description_->fieldNumber; } -- (GPBType)type { - return description_->type; +- (GPBDataType)dataType { + return description_->dataType; +} + +- (GPBWireFormat)wireType { + return GPBWireFormatForType(description_->dataType, + GPBExtensionIsPacked(description_)); +} + +- (GPBWireFormat)alternateWireType { + NSAssert(GPBExtensionIsRepeated(description_), + @"Only valid on repeated extensions"); + return GPBWireFormatForType(description_->dataType, + !GPBExtensionIsPacked(description_)); } - (BOOL)isRepeated { - return (description_->options & GPBExtensionRepeated) != 0; + return GPBExtensionIsRepeated(description_); } - (BOOL)isMap { @@ -846,7 +927,7 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { } - (BOOL)isPackable { - return (description_->options & GPBExtensionPacked) != 0; + return GPBExtensionIsPacked(description_); } - (Class)msgClass { @@ -854,11 +935,63 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { } - (GPBEnumDescriptor *)enumDescriptor { - if (GPBTypeIsEnum(description_->type)) { + if (description_->dataType == GPBDataTypeEnum) { GPBEnumDescriptor *enumDescriptor = description_->enumDescriptorFunc(); return enumDescriptor; } return nil; } +- (id)defaultValue { + if (GPBExtensionIsRepeated(description_)) { + return nil; + } + + switch (description_->dataType) { + case GPBDataTypeBool: + return @(defaultValue_.valueBool); + case GPBDataTypeFloat: + return @(defaultValue_.valueFloat); + case GPBDataTypeDouble: + return @(defaultValue_.valueDouble); + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + case GPBDataTypeEnum: + case GPBDataTypeSFixed32: + return @(defaultValue_.valueInt32); + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + case GPBDataTypeSFixed64: + return @(defaultValue_.valueInt64); + case GPBDataTypeUInt32: + case GPBDataTypeFixed32: + return @(defaultValue_.valueUInt32); + case GPBDataTypeUInt64: + case GPBDataTypeFixed64: + return @(defaultValue_.valueUInt64); + case GPBDataTypeBytes: + // Like message fields, the default is zero length data. + return (defaultValue_.valueData ? defaultValue_.valueData + : GPBEmptyNSData()); + case GPBDataTypeString: + // Like message fields, the default is zero length string. + return (defaultValue_.valueString ? defaultValue_.valueString : @""); + case GPBDataTypeGroup: + case GPBDataTypeMessage: + return nil; + } +} + +- (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)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/GPBDescriptor_PackagePrivate.h b/objectivec/GPBDescriptor_PackagePrivate.h index b289a48b..7987d928 100644 --- a/objectivec/GPBDescriptor_PackagePrivate.h +++ b/objectivec/GPBDescriptor_PackagePrivate.h @@ -33,6 +33,7 @@ // subject to change at any time without notice. #import "GPBDescriptor.h" +#import "GPBWireFormat.h" // Describes attributes of the field. typedef NS_OPTIONS(uint32_t, GPBFieldFlags) { @@ -66,8 +67,6 @@ typedef NS_OPTIONS(uint32_t, GPBFieldFlags) { // 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, }; @@ -84,21 +83,21 @@ typedef struct GPBMessageFieldDescription { int32_t hasIndex; // Field flags. Use accessor functions below. GPBFieldFlags flags; - // Type of the ivar. - GPBType type; + // Data type of the ivar. + GPBDataType dataType; // 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. + GPBGenericValue 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; + } dataTypeSpecific; } GPBMessageFieldDescription; // Describes a oneof. @@ -133,10 +132,10 @@ typedef NS_OPTIONS(uint32_t, GPBExtensionOptions) { // An extension typedef struct GPBExtensionDescription { const char *singletonName; - GPBType type; + GPBDataType dataType; const char *extendedClass; int32_t fieldNumber; - GPBValue defaultValue; + GPBGenericValue defaultValue; const char *messageOrGroupClassName; GPBExtensionOptions options; GPBEnumDescriptorFunc enumDescriptorFunc; @@ -217,7 +216,7 @@ typedef struct GPBExtensionDescription { SEL getSel_; SEL setSel_; - SEL hasSel_; + SEL hasOrCountSel_; // *Count for map<>/repeated fields, has* otherwise. SEL setHasSel_; } @@ -254,10 +253,18 @@ typedef struct GPBExtensionDescription { @package GPBExtensionDescription *description_; } +@property(nonatomic, readonly) GPBWireFormat wireType; + +// For repeated extensions, alternateWireType is the wireType with the opposite +// value for the packable property. i.e. - if the extension was marked packed +// it would be the wire type for unpacked; if the extension was marked unpacked, +// it would be the wire type for packed. +@property(nonatomic, readonly) GPBWireFormat alternateWireType; // description has to be long lived, it is held as a raw pointer. - (instancetype)initWithExtensionDescription: - (GPBExtensionDescription *)description; + (GPBExtensionDescription *)description; +- (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other; @end CF_EXTERN_C_BEGIN @@ -267,8 +274,8 @@ GPB_INLINE BOOL GPBFieldIsMapOrArray(GPBFieldDescriptor *field) { (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0; } -GPB_INLINE GPBType GPBGetFieldType(GPBFieldDescriptor *field) { - return field->description_->type; +GPB_INLINE GPBDataType GPBGetFieldDataType(GPBFieldDescriptor *field) { + return field->description_->dataType; } GPB_INLINE int32_t GPBFieldHasIndex(GPBFieldDescriptor *field) { @@ -281,6 +288,12 @@ GPB_INLINE uint32_t GPBFieldNumber(GPBFieldDescriptor *field) { uint32_t GPBFieldTag(GPBFieldDescriptor *self); +// For repeated fields, alternateWireType is the wireType with the opposite +// value for the packable property. i.e. - if the field was marked packed it +// would be the wire type for unpacked; if the field was marked unpacked, it +// would be the wire type for packed. +uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self); + GPB_INLINE BOOL GPBPreserveUnknownFields(GPBFileSyntax syntax) { return syntax != GPBFileSyntaxProto3; } @@ -289,4 +302,17 @@ GPB_INLINE BOOL GPBHasPreservingUnknownEnumSemantics(GPBFileSyntax syntax) { return syntax == GPBFileSyntaxProto3; } +GPB_INLINE BOOL GPBExtensionIsRepeated(GPBExtensionDescription *description) { + return (description->options & GPBExtensionRepeated) != 0; +} + +GPB_INLINE BOOL GPBExtensionIsPacked(GPBExtensionDescription *description) { + return (description->options & GPBExtensionPacked) != 0; +} + +GPB_INLINE BOOL GPBExtensionIsWireFormat(GPBExtensionDescription *description) { + return (description->options & GPBExtensionSetWireFormat) != 0; +} + + CF_EXTERN_C_END diff --git a/objectivec/GPBDictionary.h b/objectivec/GPBDictionary.h index 72873ad2..cc4a698a 100644 --- a/objectivec/GPBDictionary.h +++ b/objectivec/GPBDictionary.h @@ -30,13 +30,15 @@ #import <Foundation/Foundation.h> -#import "GPBTypes.h" +#import "GPBRuntimeTypes.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. +NS_ASSUME_NONNULL_BEGIN + //%PDDM-EXPAND DECLARE_DICTIONARIES() // This block of code is generated, do not edit it directly. @@ -61,7 +63,7 @@ - (instancetype)initWithDictionary:(GPBUInt32UInt32Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(uint32_t)key value:(uint32_t *)value; +- (BOOL)valueForKey:(uint32_t)key value:(nullable uint32_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(uint32_t key, uint32_t value, BOOL *stop))block; @@ -96,7 +98,7 @@ - (instancetype)initWithDictionary:(GPBUInt32Int32Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(uint32_t)key value:(int32_t *)value; +- (BOOL)valueForKey:(uint32_t)key value:(nullable int32_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(uint32_t key, int32_t value, BOOL *stop))block; @@ -131,7 +133,7 @@ - (instancetype)initWithDictionary:(GPBUInt32UInt64Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(uint32_t)key value:(uint64_t *)value; +- (BOOL)valueForKey:(uint32_t)key value:(nullable uint64_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(uint32_t key, uint64_t value, BOOL *stop))block; @@ -166,7 +168,7 @@ - (instancetype)initWithDictionary:(GPBUInt32Int64Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(uint32_t)key value:(int64_t *)value; +- (BOOL)valueForKey:(uint32_t)key value:(nullable int64_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(uint32_t key, int64_t value, BOOL *stop))block; @@ -201,7 +203,7 @@ - (instancetype)initWithDictionary:(GPBUInt32BoolDictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(uint32_t)key value:(BOOL *)value; +- (BOOL)valueForKey:(uint32_t)key value:(nullable BOOL *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(uint32_t key, BOOL value, BOOL *stop))block; @@ -236,7 +238,7 @@ - (instancetype)initWithDictionary:(GPBUInt32FloatDictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(uint32_t)key value:(float *)value; +- (BOOL)valueForKey:(uint32_t)key value:(nullable float *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(uint32_t key, float value, BOOL *stop))block; @@ -271,7 +273,7 @@ - (instancetype)initWithDictionary:(GPBUInt32DoubleDictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(uint32_t)key value:(double *)value; +- (BOOL)valueForKey:(uint32_t)key value:(nullable double *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(uint32_t key, double value, BOOL *stop))block; @@ -293,32 +295,32 @@ @property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + (instancetype)dictionary; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func; ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func rawValue:(int32_t)rawValue forKey:(uint32_t)key; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func rawValues:(const int32_t [])values forKeys:(const uint32_t [])keys count:(NSUInteger)count; + (instancetype)dictionaryWithDictionary:(GPBUInt32EnumDictionary *)dictionary; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func capacity:(NSUInteger)numItems; -- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func; -- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; +- (instancetype)initWithValidationFunction:(nullable 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 +- (instancetype)initWithValidationFunction:(nullable 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; +- (BOOL)valueForKey:(uint32_t)key value:(nullable int32_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(uint32_t key, int32_t value, BOOL *stop))block; @@ -326,7 +328,7 @@ // 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; +- (BOOL)valueForKey:(uint32_t)key rawValue:(nullable int32_t *)rawValue; - (void)enumerateKeysAndRawValuesUsingBlock: (void (^)(uint32_t key, int32_t rawValue, BOOL *stop))block; @@ -407,7 +409,7 @@ - (instancetype)initWithDictionary:(GPBInt32UInt32Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(int32_t)key value:(uint32_t *)value; +- (BOOL)valueForKey:(int32_t)key value:(nullable uint32_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(int32_t key, uint32_t value, BOOL *stop))block; @@ -442,7 +444,7 @@ - (instancetype)initWithDictionary:(GPBInt32Int32Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(int32_t)key value:(int32_t *)value; +- (BOOL)valueForKey:(int32_t)key value:(nullable int32_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(int32_t key, int32_t value, BOOL *stop))block; @@ -477,7 +479,7 @@ - (instancetype)initWithDictionary:(GPBInt32UInt64Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(int32_t)key value:(uint64_t *)value; +- (BOOL)valueForKey:(int32_t)key value:(nullable uint64_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(int32_t key, uint64_t value, BOOL *stop))block; @@ -512,7 +514,7 @@ - (instancetype)initWithDictionary:(GPBInt32Int64Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(int32_t)key value:(int64_t *)value; +- (BOOL)valueForKey:(int32_t)key value:(nullable int64_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(int32_t key, int64_t value, BOOL *stop))block; @@ -547,7 +549,7 @@ - (instancetype)initWithDictionary:(GPBInt32BoolDictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(int32_t)key value:(BOOL *)value; +- (BOOL)valueForKey:(int32_t)key value:(nullable BOOL *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(int32_t key, BOOL value, BOOL *stop))block; @@ -582,7 +584,7 @@ - (instancetype)initWithDictionary:(GPBInt32FloatDictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(int32_t)key value:(float *)value; +- (BOOL)valueForKey:(int32_t)key value:(nullable float *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(int32_t key, float value, BOOL *stop))block; @@ -617,7 +619,7 @@ - (instancetype)initWithDictionary:(GPBInt32DoubleDictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(int32_t)key value:(double *)value; +- (BOOL)valueForKey:(int32_t)key value:(nullable double *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(int32_t key, double value, BOOL *stop))block; @@ -639,32 +641,32 @@ @property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + (instancetype)dictionary; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func; ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func rawValue:(int32_t)rawValue forKey:(int32_t)key; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func rawValues:(const int32_t [])values forKeys:(const int32_t [])keys count:(NSUInteger)count; + (instancetype)dictionaryWithDictionary:(GPBInt32EnumDictionary *)dictionary; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func capacity:(NSUInteger)numItems; -- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func; -- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; +- (instancetype)initWithValidationFunction:(nullable 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 +- (instancetype)initWithValidationFunction:(nullable 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; +- (BOOL)valueForKey:(int32_t)key value:(nullable int32_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(int32_t key, int32_t value, BOOL *stop))block; @@ -672,7 +674,7 @@ // 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; +- (BOOL)valueForKey:(int32_t)key rawValue:(nullable int32_t *)rawValue; - (void)enumerateKeysAndRawValuesUsingBlock: (void (^)(int32_t key, int32_t rawValue, BOOL *stop))block; @@ -753,7 +755,7 @@ - (instancetype)initWithDictionary:(GPBUInt64UInt32Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(uint64_t)key value:(uint32_t *)value; +- (BOOL)valueForKey:(uint64_t)key value:(nullable uint32_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(uint64_t key, uint32_t value, BOOL *stop))block; @@ -788,7 +790,7 @@ - (instancetype)initWithDictionary:(GPBUInt64Int32Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(uint64_t)key value:(int32_t *)value; +- (BOOL)valueForKey:(uint64_t)key value:(nullable int32_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(uint64_t key, int32_t value, BOOL *stop))block; @@ -823,7 +825,7 @@ - (instancetype)initWithDictionary:(GPBUInt64UInt64Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(uint64_t)key value:(uint64_t *)value; +- (BOOL)valueForKey:(uint64_t)key value:(nullable uint64_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(uint64_t key, uint64_t value, BOOL *stop))block; @@ -858,7 +860,7 @@ - (instancetype)initWithDictionary:(GPBUInt64Int64Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(uint64_t)key value:(int64_t *)value; +- (BOOL)valueForKey:(uint64_t)key value:(nullable int64_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(uint64_t key, int64_t value, BOOL *stop))block; @@ -893,7 +895,7 @@ - (instancetype)initWithDictionary:(GPBUInt64BoolDictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(uint64_t)key value:(BOOL *)value; +- (BOOL)valueForKey:(uint64_t)key value:(nullable BOOL *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(uint64_t key, BOOL value, BOOL *stop))block; @@ -928,7 +930,7 @@ - (instancetype)initWithDictionary:(GPBUInt64FloatDictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(uint64_t)key value:(float *)value; +- (BOOL)valueForKey:(uint64_t)key value:(nullable float *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(uint64_t key, float value, BOOL *stop))block; @@ -963,7 +965,7 @@ - (instancetype)initWithDictionary:(GPBUInt64DoubleDictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(uint64_t)key value:(double *)value; +- (BOOL)valueForKey:(uint64_t)key value:(nullable double *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(uint64_t key, double value, BOOL *stop))block; @@ -985,32 +987,32 @@ @property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + (instancetype)dictionary; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func; ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func rawValue:(int32_t)rawValue forKey:(uint64_t)key; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func rawValues:(const int32_t [])values forKeys:(const uint64_t [])keys count:(NSUInteger)count; + (instancetype)dictionaryWithDictionary:(GPBUInt64EnumDictionary *)dictionary; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func capacity:(NSUInteger)numItems; -- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func; -- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; +- (instancetype)initWithValidationFunction:(nullable 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 +- (instancetype)initWithValidationFunction:(nullable 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; +- (BOOL)valueForKey:(uint64_t)key value:(nullable int32_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(uint64_t key, int32_t value, BOOL *stop))block; @@ -1018,7 +1020,7 @@ // 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; +- (BOOL)valueForKey:(uint64_t)key rawValue:(nullable int32_t *)rawValue; - (void)enumerateKeysAndRawValuesUsingBlock: (void (^)(uint64_t key, int32_t rawValue, BOOL *stop))block; @@ -1099,7 +1101,7 @@ - (instancetype)initWithDictionary:(GPBInt64UInt32Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(int64_t)key value:(uint32_t *)value; +- (BOOL)valueForKey:(int64_t)key value:(nullable uint32_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(int64_t key, uint32_t value, BOOL *stop))block; @@ -1134,7 +1136,7 @@ - (instancetype)initWithDictionary:(GPBInt64Int32Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(int64_t)key value:(int32_t *)value; +- (BOOL)valueForKey:(int64_t)key value:(nullable int32_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(int64_t key, int32_t value, BOOL *stop))block; @@ -1169,7 +1171,7 @@ - (instancetype)initWithDictionary:(GPBInt64UInt64Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(int64_t)key value:(uint64_t *)value; +- (BOOL)valueForKey:(int64_t)key value:(nullable uint64_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(int64_t key, uint64_t value, BOOL *stop))block; @@ -1204,7 +1206,7 @@ - (instancetype)initWithDictionary:(GPBInt64Int64Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(int64_t)key value:(int64_t *)value; +- (BOOL)valueForKey:(int64_t)key value:(nullable int64_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(int64_t key, int64_t value, BOOL *stop))block; @@ -1239,7 +1241,7 @@ - (instancetype)initWithDictionary:(GPBInt64BoolDictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(int64_t)key value:(BOOL *)value; +- (BOOL)valueForKey:(int64_t)key value:(nullable BOOL *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(int64_t key, BOOL value, BOOL *stop))block; @@ -1274,7 +1276,7 @@ - (instancetype)initWithDictionary:(GPBInt64FloatDictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(int64_t)key value:(float *)value; +- (BOOL)valueForKey:(int64_t)key value:(nullable float *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(int64_t key, float value, BOOL *stop))block; @@ -1309,7 +1311,7 @@ - (instancetype)initWithDictionary:(GPBInt64DoubleDictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(int64_t)key value:(double *)value; +- (BOOL)valueForKey:(int64_t)key value:(nullable double *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(int64_t key, double value, BOOL *stop))block; @@ -1331,32 +1333,32 @@ @property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + (instancetype)dictionary; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func; ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func rawValue:(int32_t)rawValue forKey:(int64_t)key; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func rawValues:(const int32_t [])values forKeys:(const int64_t [])keys count:(NSUInteger)count; + (instancetype)dictionaryWithDictionary:(GPBInt64EnumDictionary *)dictionary; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func capacity:(NSUInteger)numItems; -- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func; -- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; +- (instancetype)initWithValidationFunction:(nullable 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 +- (instancetype)initWithValidationFunction:(nullable 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; +- (BOOL)valueForKey:(int64_t)key value:(nullable int32_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(int64_t key, int32_t value, BOOL *stop))block; @@ -1364,7 +1366,7 @@ // 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; +- (BOOL)valueForKey:(int64_t)key rawValue:(nullable int32_t *)rawValue; - (void)enumerateKeysAndRawValuesUsingBlock: (void (^)(int64_t key, int32_t rawValue, BOOL *stop))block; @@ -1445,7 +1447,7 @@ - (instancetype)initWithDictionary:(GPBBoolUInt32Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(BOOL)key value:(uint32_t *)value; +- (BOOL)valueForKey:(BOOL)key value:(nullable uint32_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(BOOL key, uint32_t value, BOOL *stop))block; @@ -1480,7 +1482,7 @@ - (instancetype)initWithDictionary:(GPBBoolInt32Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(BOOL)key value:(int32_t *)value; +- (BOOL)valueForKey:(BOOL)key value:(nullable int32_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(BOOL key, int32_t value, BOOL *stop))block; @@ -1515,7 +1517,7 @@ - (instancetype)initWithDictionary:(GPBBoolUInt64Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(BOOL)key value:(uint64_t *)value; +- (BOOL)valueForKey:(BOOL)key value:(nullable uint64_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(BOOL key, uint64_t value, BOOL *stop))block; @@ -1550,7 +1552,7 @@ - (instancetype)initWithDictionary:(GPBBoolInt64Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(BOOL)key value:(int64_t *)value; +- (BOOL)valueForKey:(BOOL)key value:(nullable int64_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(BOOL key, int64_t value, BOOL *stop))block; @@ -1585,7 +1587,7 @@ - (instancetype)initWithDictionary:(GPBBoolBoolDictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(BOOL)key value:(BOOL *)value; +- (BOOL)valueForKey:(BOOL)key value:(nullable BOOL *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(BOOL key, BOOL value, BOOL *stop))block; @@ -1620,7 +1622,7 @@ - (instancetype)initWithDictionary:(GPBBoolFloatDictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(BOOL)key value:(float *)value; +- (BOOL)valueForKey:(BOOL)key value:(nullable float *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(BOOL key, float value, BOOL *stop))block; @@ -1655,7 +1657,7 @@ - (instancetype)initWithDictionary:(GPBBoolDoubleDictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(BOOL)key value:(double *)value; +- (BOOL)valueForKey:(BOOL)key value:(nullable double *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(BOOL key, double value, BOOL *stop))block; @@ -1677,32 +1679,32 @@ @property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + (instancetype)dictionary; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func; ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func rawValue:(int32_t)rawValue forKey:(BOOL)key; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func rawValues:(const int32_t [])values forKeys:(const BOOL [])keys count:(NSUInteger)count; + (instancetype)dictionaryWithDictionary:(GPBBoolEnumDictionary *)dictionary; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func capacity:(NSUInteger)numItems; -- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func; -- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; +- (instancetype)initWithValidationFunction:(nullable 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 +- (instancetype)initWithValidationFunction:(nullable 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; +- (BOOL)valueForKey:(BOOL)key value:(nullable int32_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(BOOL key, int32_t value, BOOL *stop))block; @@ -1710,7 +1712,7 @@ // 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; +- (BOOL)valueForKey:(BOOL)key rawValue:(nullable int32_t *)rawValue; - (void)enumerateKeysAndRawValuesUsingBlock: (void (^)(BOOL key, int32_t rawValue, BOOL *stop))block; @@ -1791,7 +1793,7 @@ - (instancetype)initWithDictionary:(GPBStringUInt32Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(NSString *)key value:(uint32_t *)value; +- (BOOL)valueForKey:(NSString *)key value:(nullable uint32_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(NSString *key, uint32_t value, BOOL *stop))block; @@ -1826,7 +1828,7 @@ - (instancetype)initWithDictionary:(GPBStringInt32Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(NSString *)key value:(int32_t *)value; +- (BOOL)valueForKey:(NSString *)key value:(nullable int32_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(NSString *key, int32_t value, BOOL *stop))block; @@ -1861,7 +1863,7 @@ - (instancetype)initWithDictionary:(GPBStringUInt64Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(NSString *)key value:(uint64_t *)value; +- (BOOL)valueForKey:(NSString *)key value:(nullable uint64_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(NSString *key, uint64_t value, BOOL *stop))block; @@ -1896,7 +1898,7 @@ - (instancetype)initWithDictionary:(GPBStringInt64Dictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(NSString *)key value:(int64_t *)value; +- (BOOL)valueForKey:(NSString *)key value:(nullable int64_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(NSString *key, int64_t value, BOOL *stop))block; @@ -1931,7 +1933,7 @@ - (instancetype)initWithDictionary:(GPBStringBoolDictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(NSString *)key value:(BOOL *)value; +- (BOOL)valueForKey:(NSString *)key value:(nullable BOOL *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(NSString *key, BOOL value, BOOL *stop))block; @@ -1966,7 +1968,7 @@ - (instancetype)initWithDictionary:(GPBStringFloatDictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(NSString *)key value:(float *)value; +- (BOOL)valueForKey:(NSString *)key value:(nullable float *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(NSString *key, float value, BOOL *stop))block; @@ -2001,7 +2003,7 @@ - (instancetype)initWithDictionary:(GPBStringDoubleDictionary *)dictionary; - (instancetype)initWithCapacity:(NSUInteger)numItems; -- (BOOL)valueForKey:(NSString *)key value:(double *)value; +- (BOOL)valueForKey:(NSString *)key value:(nullable double *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(NSString *key, double value, BOOL *stop))block; @@ -2023,32 +2025,32 @@ @property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; + (instancetype)dictionary; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func; ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func rawValue:(int32_t)rawValue forKey:(NSString *)key; -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func ++ (instancetype)dictionaryWithValidationFunction:(nullable 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 ++ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func capacity:(NSUInteger)numItems; -- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func; -- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func +- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; +- (instancetype)initWithValidationFunction:(nullable 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 +- (instancetype)initWithValidationFunction:(nullable 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; +- (BOOL)valueForKey:(NSString *)key value:(nullable int32_t *)value; - (void)enumerateKeysAndValuesUsingBlock: (void (^)(NSString *key, int32_t value, BOOL *stop))block; @@ -2056,7 +2058,7 @@ // 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; +- (BOOL)valueForKey:(NSString *)key rawValue:(nullable int32_t *)rawValue; - (void)enumerateKeysAndRawValuesUsingBlock: (void (^)(NSString *key, int32_t rawValue, BOOL *stop))block; @@ -2083,6 +2085,8 @@ //%PDDM-EXPAND-END DECLARE_DICTIONARIES() +NS_ASSUME_NONNULL_END + //%PDDM-DEFINE DECLARE_DICTIONARIES() //%DICTIONARY_INTERFACES_FOR_POD_KEY(UInt32, uint32_t) //%DICTIONARY_INTERFACES_FOR_POD_KEY(Int32, int32_t) @@ -2107,7 +2111,7 @@ //%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; +//%- (BOOL)valueForKey:(KEY_TYPE)key value:(nullable 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) @@ -2160,25 +2164,25 @@ //%@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; //% //%+ (instancetype)dictionary; -//%+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func; -//%+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func +//%+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func; +//%+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func //% rawValue:(VALUE_TYPE)rawValue //% forKey:(KEY_TYPE##KisP$S##KisP)key; -//%+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func +//%+ (instancetype)dictionaryWithValidationFunction:(nullable 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 +//%+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func //% capacity:(NSUInteger)numItems; //% -//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func; -//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func +//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func; +//%- (instancetype)initWithValidationFunction:(nullable 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 +//%- (instancetype)initWithValidationFunction:(nullable GPBEnumValidationFunc)func //% capacity:(NSUInteger)numItems; //% //%// These will return kGPBUnrecognizedEnumeratorValue if the value for the key @@ -2190,7 +2194,7 @@ //%// 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; +//%- (BOOL)valueForKey:(KEY_TYPE##KisP$S##KisP)key rawValue:(nullable VALUE_TYPE *)rawValue; //% //%- (void)enumerateKeysAndRawValuesUsingBlock: //% (void (^)(KEY_TYPE KisP##key, VALUE_TYPE rawValue, BOOL *stop))block; diff --git a/objectivec/GPBDictionary.m b/objectivec/GPBDictionary.m index 3769c697..df634279 100644 --- a/objectivec/GPBDictionary.m +++ b/objectivec/GPBDictionary.m @@ -55,64 +55,64 @@ static BOOL DictDefault_IsValidValue(int32_t value) { 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) { -//% 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); +//%PDDM-DEFINE SERIALIZE_SUPPORT_2_TYPE(VALUE_NAME, VALUE_TYPE, GPBDATATYPE_NAME1, GPBDATATYPE_NAME2) +//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) { +//% if (dataType == GPBDataType##GPBDATATYPE_NAME1) { +//% return GPBCompute##GPBDATATYPE_NAME1##Size(fieldNum, value); +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) { +//% return GPBCompute##GPBDATATYPE_NAME2##Size(fieldNum, value); //% } else { -//% NSCAssert(NO, @"Unexpected type %d", wireType); +//% NSCAssert(NO, @"Unexpected type %d", dataType); //% return 0; //% } //%} //% -//%GPB_INLINE void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBType 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]; +//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) { +//% if (dataType == GPBDataType##GPBDATATYPE_NAME1) { +//% [stream write##GPBDATATYPE_NAME1##:fieldNum value:value]; +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) { +//% [stream write##GPBDATATYPE_NAME2##:fieldNum value:value]; //% } else { -//% NSCAssert(NO, @"Unexpected type %d", wireType); +//% NSCAssert(NO, @"Unexpected type %d", dataType); //% } //%} //% -//%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) { -//% 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 if (wireType == GPBType##GPBTYPE_NAME3) { -//% return GPBCompute##GPBTYPE_NAME3##Size(fieldNum, value); +//%PDDM-DEFINE SERIALIZE_SUPPORT_3_TYPE(VALUE_NAME, VALUE_TYPE, GPBDATATYPE_NAME1, GPBDATATYPE_NAME2, GPBDATATYPE_NAME3) +//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) { +//% if (dataType == GPBDataType##GPBDATATYPE_NAME1) { +//% return GPBCompute##GPBDATATYPE_NAME1##Size(fieldNum, value); +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) { +//% return GPBCompute##GPBDATATYPE_NAME2##Size(fieldNum, value); +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME3) { +//% return GPBCompute##GPBDATATYPE_NAME3##Size(fieldNum, value); //% } else { -//% NSCAssert(NO, @"Unexpected type %d", wireType); +//% NSCAssert(NO, @"Unexpected type %d", dataType); //% return 0; //% } //%} //% -//%GPB_INLINE void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBType 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 if (wireType == GPBType##GPBTYPE_NAME3) { -//% [stream write##GPBTYPE_NAME3##:fieldNum value:value]; +//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) { +//% if (dataType == GPBDataType##GPBDATATYPE_NAME1) { +//% [stream write##GPBDATATYPE_NAME1##:fieldNum value:value]; +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) { +//% [stream write##GPBDATATYPE_NAME2##:fieldNum value:value]; +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME3) { +//% [stream write##GPBDATATYPE_NAME3##:fieldNum value:value]; //% } else { -//% NSCAssert(NO, @"Unexpected type %d", wireType); +//% NSCAssert(NO, @"Unexpected type %d", dataType); //% } //%} //% //%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); -//% #pragma unused(wireType) // For when asserts are off in release. +//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE VisP##value, uint32_t fieldNum, GPBDataType dataType) { +//% NSCAssert(dataType == GPBDataType##VALUE_NAME, @"bad type: %d", dataType); +//% #pragma unused(dataType) // For when asserts are off in release. //% 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); -//% #pragma unused(wireType) // For when asserts are off in release. +//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE VisP##value, uint32_t fieldNum, GPBDataType dataType) { +//% NSCAssert(dataType == GPBDataType##VALUE_NAME, @"bad type: %d", dataType); +//% #pragma unused(dataType) // For when asserts are off in release. //% [stream write##VALUE_NAME##:fieldNum value:value]; //%} //% @@ -126,191 +126,191 @@ static BOOL DictDefault_IsValidValue(int32_t value) { //%SIMPLE_SERIALIZE_SUPPORT(Float, float, ) //%SIMPLE_SERIALIZE_SUPPORT(Double, double, ) //%SIMPLE_SERIALIZE_SUPPORT(String, NSString, *) -//%SERIALIZE_SUPPORT_3_TYPE(Object, id, Message, String, Data) +//%SERIALIZE_SUPPORT_3_TYPE(Object, id, Message, String, Bytes) //%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) { - if (wireType == GPBTypeInt32) { +static size_t ComputeDictInt32FieldSize(int32_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeInt32) { return GPBComputeInt32Size(fieldNum, value); - } else if (wireType == GPBTypeSInt32) { + } else if (dataType == GPBDataTypeSInt32) { return GPBComputeSInt32Size(fieldNum, value); - } else if (wireType == GPBTypeSFixed32) { + } else if (dataType == GPBDataTypeSFixed32) { return GPBComputeSFixed32Size(fieldNum, value); } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); return 0; } } -GPB_INLINE void WriteDictInt32Field(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBType wireType) { - if (wireType == GPBTypeInt32) { +static void WriteDictInt32Field(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeInt32) { [stream writeInt32:fieldNum value:value]; - } else if (wireType == GPBTypeSInt32) { + } else if (dataType == GPBDataTypeSInt32) { [stream writeSInt32:fieldNum value:value]; - } else if (wireType == GPBTypeSFixed32) { + } else if (dataType == GPBDataTypeSFixed32) { [stream writeSFixed32:fieldNum value:value]; } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); } } -GPB_INLINE size_t ComputeDictUInt32FieldSize(uint32_t value, uint32_t fieldNum, GPBType wireType) { - if (wireType == GPBTypeUInt32) { +static size_t ComputeDictUInt32FieldSize(uint32_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeUInt32) { return GPBComputeUInt32Size(fieldNum, value); - } else if (wireType == GPBTypeFixed32) { + } else if (dataType == GPBDataTypeFixed32) { return GPBComputeFixed32Size(fieldNum, value); } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); return 0; } } -GPB_INLINE void WriteDictUInt32Field(GPBCodedOutputStream *stream, uint32_t value, uint32_t fieldNum, GPBType wireType) { - if (wireType == GPBTypeUInt32) { +static void WriteDictUInt32Field(GPBCodedOutputStream *stream, uint32_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeUInt32) { [stream writeUInt32:fieldNum value:value]; - } else if (wireType == GPBTypeFixed32) { + } else if (dataType == GPBDataTypeFixed32) { [stream writeFixed32:fieldNum value:value]; } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); } } -GPB_INLINE size_t ComputeDictInt64FieldSize(int64_t value, uint32_t fieldNum, GPBType wireType) { - if (wireType == GPBTypeInt64) { +static size_t ComputeDictInt64FieldSize(int64_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeInt64) { return GPBComputeInt64Size(fieldNum, value); - } else if (wireType == GPBTypeSInt64) { + } else if (dataType == GPBDataTypeSInt64) { return GPBComputeSInt64Size(fieldNum, value); - } else if (wireType == GPBTypeSFixed64) { + } else if (dataType == GPBDataTypeSFixed64) { return GPBComputeSFixed64Size(fieldNum, value); } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); return 0; } } -GPB_INLINE void WriteDictInt64Field(GPBCodedOutputStream *stream, int64_t value, uint32_t fieldNum, GPBType wireType) { - if (wireType == GPBTypeInt64) { +static void WriteDictInt64Field(GPBCodedOutputStream *stream, int64_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeInt64) { [stream writeInt64:fieldNum value:value]; - } else if (wireType == GPBTypeSInt64) { + } else if (dataType == GPBDataTypeSInt64) { [stream writeSInt64:fieldNum value:value]; - } else if (wireType == GPBTypeSFixed64) { + } else if (dataType == GPBDataTypeSFixed64) { [stream writeSFixed64:fieldNum value:value]; } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); } } -GPB_INLINE size_t ComputeDictUInt64FieldSize(uint64_t value, uint32_t fieldNum, GPBType wireType) { - if (wireType == GPBTypeUInt64) { +static size_t ComputeDictUInt64FieldSize(uint64_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeUInt64) { return GPBComputeUInt64Size(fieldNum, value); - } else if (wireType == GPBTypeFixed64) { + } else if (dataType == GPBDataTypeFixed64) { return GPBComputeFixed64Size(fieldNum, value); } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); return 0; } } -GPB_INLINE void WriteDictUInt64Field(GPBCodedOutputStream *stream, uint64_t value, uint32_t fieldNum, GPBType wireType) { - if (wireType == GPBTypeUInt64) { +static void WriteDictUInt64Field(GPBCodedOutputStream *stream, uint64_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeUInt64) { [stream writeUInt64:fieldNum value:value]; - } else if (wireType == GPBTypeFixed64) { + } else if (dataType == GPBDataTypeFixed64) { [stream writeFixed64:fieldNum value:value]; } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); } } -GPB_INLINE size_t ComputeDictBoolFieldSize(BOOL value, uint32_t fieldNum, GPBType wireType) { - NSCAssert(wireType == GPBTypeBool, @"bad type: %d", wireType); - #pragma unused(wireType) // For when asserts are off in release. +static size_t ComputeDictBoolFieldSize(BOOL value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeBool, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. return GPBComputeBoolSize(fieldNum, value); } -GPB_INLINE void WriteDictBoolField(GPBCodedOutputStream *stream, BOOL value, uint32_t fieldNum, GPBType wireType) { - NSCAssert(wireType == GPBTypeBool, @"bad type: %d", wireType); - #pragma unused(wireType) // For when asserts are off in release. +static void WriteDictBoolField(GPBCodedOutputStream *stream, BOOL value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeBool, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. [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); - #pragma unused(wireType) // For when asserts are off in release. +static size_t ComputeDictEnumFieldSize(int32_t value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeEnum, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. 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); - #pragma unused(wireType) // For when asserts are off in release. +static void WriteDictEnumField(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeEnum, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. [stream writeEnum:fieldNum value:value]; } -GPB_INLINE size_t ComputeDictFloatFieldSize(float value, uint32_t fieldNum, GPBType wireType) { - NSCAssert(wireType == GPBTypeFloat, @"bad type: %d", wireType); - #pragma unused(wireType) // For when asserts are off in release. +static size_t ComputeDictFloatFieldSize(float value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeFloat, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. return GPBComputeFloatSize(fieldNum, value); } -GPB_INLINE void WriteDictFloatField(GPBCodedOutputStream *stream, float value, uint32_t fieldNum, GPBType wireType) { - NSCAssert(wireType == GPBTypeFloat, @"bad type: %d", wireType); - #pragma unused(wireType) // For when asserts are off in release. +static void WriteDictFloatField(GPBCodedOutputStream *stream, float value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeFloat, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. [stream writeFloat:fieldNum value:value]; } -GPB_INLINE size_t ComputeDictDoubleFieldSize(double value, uint32_t fieldNum, GPBType wireType) { - NSCAssert(wireType == GPBTypeDouble, @"bad type: %d", wireType); - #pragma unused(wireType) // For when asserts are off in release. +static size_t ComputeDictDoubleFieldSize(double value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeDouble, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. return GPBComputeDoubleSize(fieldNum, value); } -GPB_INLINE void WriteDictDoubleField(GPBCodedOutputStream *stream, double value, uint32_t fieldNum, GPBType wireType) { - NSCAssert(wireType == GPBTypeDouble, @"bad type: %d", wireType); - #pragma unused(wireType) // For when asserts are off in release. +static void WriteDictDoubleField(GPBCodedOutputStream *stream, double value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeDouble, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. [stream writeDouble:fieldNum value:value]; } -GPB_INLINE size_t ComputeDictStringFieldSize(NSString *value, uint32_t fieldNum, GPBType wireType) { - NSCAssert(wireType == GPBTypeString, @"bad type: %d", wireType); - #pragma unused(wireType) // For when asserts are off in release. +static size_t ComputeDictStringFieldSize(NSString *value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeString, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. return GPBComputeStringSize(fieldNum, value); } -GPB_INLINE void WriteDictStringField(GPBCodedOutputStream *stream, NSString *value, uint32_t fieldNum, GPBType wireType) { - NSCAssert(wireType == GPBTypeString, @"bad type: %d", wireType); - #pragma unused(wireType) // For when asserts are off in release. +static void WriteDictStringField(GPBCodedOutputStream *stream, NSString *value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeString, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. [stream writeString:fieldNum value:value]; } -GPB_INLINE size_t ComputeDictObjectFieldSize(id value, uint32_t fieldNum, GPBType wireType) { - if (wireType == GPBTypeMessage) { +static size_t ComputeDictObjectFieldSize(id value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeMessage) { return GPBComputeMessageSize(fieldNum, value); - } else if (wireType == GPBTypeString) { + } else if (dataType == GPBDataTypeString) { return GPBComputeStringSize(fieldNum, value); - } else if (wireType == GPBTypeData) { - return GPBComputeDataSize(fieldNum, value); + } else if (dataType == GPBDataTypeBytes) { + return GPBComputeBytesSize(fieldNum, value); } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); return 0; } } -GPB_INLINE void WriteDictObjectField(GPBCodedOutputStream *stream, id value, uint32_t fieldNum, GPBType wireType) { - if (wireType == GPBTypeMessage) { +static void WriteDictObjectField(GPBCodedOutputStream *stream, id value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeMessage) { [stream writeMessage:fieldNum value:value]; - } else if (wireType == GPBTypeString) { + } else if (dataType == GPBDataTypeString) { [stream writeString:fieldNum value:value]; - } else if (wireType == GPBTypeData) { - [stream writeData:fieldNum value:value]; + } else if (dataType == GPBDataTypeBytes) { + [stream writeBytes:fieldNum value:value]; } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); } } //%PDDM-EXPAND-END SERIALIZE_SUPPORT_HELPERS() size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) { - GPBType mapValueType = GPBGetFieldType(field); + GPBDataType mapValueType = GPBGetFieldDataType(field); __block size_t result = 0; [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) { #pragma unused(stop) @@ -318,7 +318,7 @@ size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict, GPBFieldDescri msgSize += ComputeDictObjectFieldSize(obj, kMapValueFieldNumber, mapValueType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * dict.count; return result; } @@ -326,8 +326,8 @@ size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict, GPBFieldDescri void GPBDictionaryWriteToStreamInternalHelper(GPBCodedOutputStream *outputStream, NSDictionary *dict, GPBFieldDescriptor *field) { - NSCAssert(field.mapKeyType == GPBTypeString, @"Unexpected key type"); - GPBType mapValueType = GPBGetFieldType(field); + NSCAssert(field.mapKeyDataType == GPBDataTypeString, @"Unexpected key type"); + GPBDataType mapValueType = GPBGetFieldDataType(field); uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) { #pragma unused(stop) @@ -345,8 +345,8 @@ void GPBDictionaryWriteToStreamInternalHelper(GPBCodedOutputStream *outputStream } BOOL GPBDictionaryIsInitializedInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) { - NSCAssert(field.mapKeyType == GPBTypeString, @"Unexpected key type"); - NSCAssert(GPBGetFieldType(field) == GPBTypeMessage, @"Unexpected value type"); + NSCAssert(field.mapKeyDataType == GPBDataTypeString, @"Unexpected key type"); + NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeMessage, @"Unexpected value type"); #pragma unused(field) // For when asserts are off in release. for (GPBMessage *msg in [dict objectEnumerator]) { if (!msg.initialized) { @@ -358,69 +358,69 @@ BOOL GPBDictionaryIsInitializedInternalHelper(NSDictionary *dict, GPBFieldDescri // Note: if the type is an object, it the retain pass back to the caller. static void ReadValue(GPBCodedInputStream *stream, - GPBValue *valueToFill, - GPBType type, + GPBGenericValue *valueToFill, + GPBDataType type, GPBExtensionRegistry *registry, GPBFieldDescriptor *field) { switch (type) { - case GPBTypeBool: + case GPBDataTypeBool: valueToFill->valueBool = GPBCodedInputStreamReadBool(&stream->state_); break; - case GPBTypeFixed32: + case GPBDataTypeFixed32: valueToFill->valueUInt32 = GPBCodedInputStreamReadFixed32(&stream->state_); break; - case GPBTypeSFixed32: + case GPBDataTypeSFixed32: valueToFill->valueInt32 = GPBCodedInputStreamReadSFixed32(&stream->state_); break; - case GPBTypeFloat: + case GPBDataTypeFloat: valueToFill->valueFloat = GPBCodedInputStreamReadFloat(&stream->state_); break; - case GPBTypeFixed64: + case GPBDataTypeFixed64: valueToFill->valueUInt64 = GPBCodedInputStreamReadFixed64(&stream->state_); break; - case GPBTypeSFixed64: + case GPBDataTypeSFixed64: valueToFill->valueInt64 = GPBCodedInputStreamReadSFixed64(&stream->state_); break; - case GPBTypeDouble: + case GPBDataTypeDouble: valueToFill->valueDouble = GPBCodedInputStreamReadDouble(&stream->state_); break; - case GPBTypeInt32: + case GPBDataTypeInt32: valueToFill->valueInt32 = GPBCodedInputStreamReadInt32(&stream->state_); break; - case GPBTypeInt64: + case GPBDataTypeInt64: valueToFill->valueInt64 = GPBCodedInputStreamReadInt32(&stream->state_); break; - case GPBTypeSInt32: + case GPBDataTypeSInt32: valueToFill->valueInt32 = GPBCodedInputStreamReadSInt32(&stream->state_); break; - case GPBTypeSInt64: + case GPBDataTypeSInt64: valueToFill->valueInt64 = GPBCodedInputStreamReadSInt64(&stream->state_); break; - case GPBTypeUInt32: + case GPBDataTypeUInt32: valueToFill->valueUInt32 = GPBCodedInputStreamReadUInt32(&stream->state_); break; - case GPBTypeUInt64: + case GPBDataTypeUInt64: valueToFill->valueUInt64 = GPBCodedInputStreamReadUInt64(&stream->state_); break; - case GPBTypeData: + case GPBDataTypeBytes: [valueToFill->valueData release]; - valueToFill->valueData = GPBCodedInputStreamReadRetainedData(&stream->state_); + valueToFill->valueData = GPBCodedInputStreamReadRetainedBytes(&stream->state_); break; - case GPBTypeString: + case GPBDataTypeString: [valueToFill->valueString release]; valueToFill->valueString = GPBCodedInputStreamReadRetainedString(&stream->state_); break; - case GPBTypeMessage: { + case GPBDataTypeMessage: { GPBMessage *message = [[field.msgClass alloc] init]; [stream readMessage:message extensionRegistry:registry]; [valueToFill->valueMessage release]; valueToFill->valueMessage = message; break; } - case GPBTypeGroup: + case GPBDataTypeGroup: NSCAssert(NO, @"Can't happen"); break; - case GPBTypeEnum: + case GPBDataTypeEnum: valueToFill->valueEnum = GPBCodedInputStreamReadEnum(&stream->state_); break; } @@ -431,30 +431,30 @@ void GPBDictionaryReadEntry(id mapDictionary, GPBExtensionRegistry *registry, GPBFieldDescriptor *field, GPBMessage *parentMessage) { - GPBType keyType = field.mapKeyType; - GPBType valueType = GPBGetFieldType(field); + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = GPBGetFieldDataType(field); - GPBValue key; - GPBValue value; + GPBGenericValue key; + GPBGenericValue value; // Zero them (but pick up any enum default for proto2). key.valueString = value.valueString = nil; - if (valueType == GPBTypeEnum) { + if (valueDataType == GPBDataTypeEnum) { value = field.defaultValue; } GPBCodedInputStreamState *state = &stream->state_; uint32_t keyTag = - GPBWireFormatMakeTag(kMapKeyFieldNumber, GPBWireFormatForType(keyType, NO)); + GPBWireFormatMakeTag(kMapKeyFieldNumber, GPBWireFormatForType(keyDataType, NO)); uint32_t valueTag = - GPBWireFormatMakeTag(kMapValueFieldNumber, GPBWireFormatForType(valueType, NO)); + GPBWireFormatMakeTag(kMapValueFieldNumber, GPBWireFormatForType(valueDataType, NO)); BOOL hitError = NO; while (YES) { uint32_t tag = GPBCodedInputStreamReadTag(state); if (tag == keyTag) { - ReadValue(stream, &key, keyType, registry, field); + ReadValue(stream, &key, keyDataType, registry, field); } else if (tag == valueTag) { - ReadValue(stream, &value, valueType, registry, field); + ReadValue(stream, &value, valueDataType, registry, field); } else if (tag == 0) { // zero signals EOF / limit reached break; @@ -468,18 +468,18 @@ void GPBDictionaryReadEntry(id mapDictionary, if (!hitError) { // Handle the special defaults and/or missing key/value. - if ((keyType == GPBTypeString) && (key.valueString == nil)) { + if ((keyDataType == GPBDataTypeString) && (key.valueString == nil)) { key.valueString = [@"" retain]; } - if (GPBTypeIsObject(valueType) && value.valueString == nil) { - switch (valueType) { - case GPBTypeString: + if (GPBDataTypeIsObject(valueDataType) && value.valueString == nil) { + switch (valueDataType) { + case GPBDataTypeString: value.valueString = [@"" retain]; break; - case GPBTypeData: + case GPBDataTypeBytes: value.valueData = [GPBEmptyNSData() retain]; break; - case GPBTypeMessage: { + case GPBDataTypeMessage: { value.valueMessage = [[field.msgClass alloc] init]; break; } @@ -489,30 +489,30 @@ void GPBDictionaryReadEntry(id mapDictionary, } } - if ((keyType == GPBTypeString) && GPBTypeIsObject(valueType)) { + if ((keyDataType == GPBDataTypeString) && GPBDataTypeIsObject(valueDataType)) { // mapDictionary is an NSMutableDictionary [mapDictionary setObject:value.valueString forKey:key.valueString]; } else { - if (valueType == GPBTypeEnum) { + if (valueDataType == GPBDataTypeEnum) { if (GPBHasPreservingUnknownEnumSemantics([parentMessage descriptor].file.syntax) || [field isValidEnumValue:value.valueEnum]) { - [mapDictionary setGPBValue:&value forGPBValueKey:&key]; + [mapDictionary setGPBGenericValue:&value forGPBGenericValueKey:&key]; } else { NSData *data = [mapDictionary serializedDataForUnknownValue:value.valueEnum forKey:&key - keyType:keyType]; + keyDataType:keyDataType]; [parentMessage addUnknownMapEntry:GPBFieldNumber(field) value:data]; } } else { - [mapDictionary setGPBValue:&value forGPBValueKey:&key]; + [mapDictionary setGPBGenericValue:&value forGPBGenericValueKey:&key]; } } } - if (GPBTypeIsObject(keyType)) { + if (GPBDataTypeIsObject(keyDataType)) { [key.valueString release]; } - if (GPBTypeIsObject(valueType)) { + if (GPBDataTypeIsObject(valueDataType)) { [value.valueString release]; } } @@ -834,26 +834,26 @@ void GPBDictionaryReadEntry(id mapDictionary, //% return 0; //% } //% -//% GPBType valueType = GPBGetFieldType(field); -//% GPBType keyType = field.mapKeyType; +//% GPBDataType valueDataType = GPBGetFieldDataType(field); +//% GPBDataType keyDataType = field.mapKeyDataType; //% __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); +//% size_t msgSize = ComputeDict##KEY_NAME##FieldSize(UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyDataType); +//% msgSize += ComputeDict##VALUE_NAME##FieldSize(UNWRAP##VALUE_NAME(aValue), kMapValueFieldNumber, valueDataType); //% result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; //% }]; -//% size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); +//% size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); //% result += tagSize * count; //% return result; //%} //% //%- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream //% asField:(GPBFieldDescriptor *)field { -//% GPBType valueType = GPBGetFieldType(field); -//% GPBType keyType = field.mapKeyType; +//% GPBDataType valueDataType = GPBGetFieldDataType(field); +//% GPBDataType keyDataType = field.mapKeyDataType; //% uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); //% [_dictionary enumerateKeysAndObjectsUsingBlock:^(ENUM_TYPE##KHELPER(KEY_TYPE)##aKey, //% ENUM_TYPE##VHELPER(VALUE_TYPE)##aValue, @@ -862,16 +862,17 @@ void GPBDictionaryReadEntry(id mapDictionary, //% // 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); +//% size_t msgSize = ComputeDict##KEY_NAME##FieldSize(UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyDataType); +//% msgSize += ComputeDict##VALUE_NAME##FieldSize(UNWRAP##VALUE_NAME(aValue), kMapValueFieldNumber, valueDataType); //% [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); +//% WriteDict##KEY_NAME##Field(outputStream, UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyDataType); +//% WriteDict##VALUE_NAME##Field(outputStream, UNWRAP##VALUE_NAME(aValue), kMapValueFieldNumber, valueDataType); //% }]; //%} //% -//%SERIAL_DATA_FOR_ENTRY_##VHELPER(KEY_NAME, VALUE_NAME)- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +//%SERIAL_DATA_FOR_ENTRY_##VHELPER(KEY_NAME, VALUE_NAME)- (void)setGPBGenericValue:(GPBGenericValue *)value +//% forGPBGenericValueKey:(GPBGenericValue *)key { //% [_dictionary setObject:WRAPPED##VHELPER(value->##GPBVALUE_##VHELPER(VALUE_NAME)##) forKey:WRAPPED##KHELPER(key->value##KEY_NAME)]; //%} //% @@ -1036,37 +1037,37 @@ void GPBDictionaryReadEntry(id mapDictionary, //%} //% //%BOOL_EXTRA_METHODS_##HELPER(Bool, VALUE_NAME)- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { -//% GPBType valueType = GPBGetFieldType(field); +//% GPBDataType valueDataType = GPBGetFieldDataType(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); +//% size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); +//% msgSize += ComputeDict##VALUE_NAME##FieldSize(_values[i], kMapValueFieldNumber, valueDataType); //% result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; //% } //% } -//% size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); +//% size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); //% result += tagSize * count; //% return result; //%} //% //%- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream //% asField:(GPBFieldDescriptor *)field { -//% GPBType valueType = GPBGetFieldType(field); +//% GPBDataType valueDataType = GPBGetFieldDataType(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); +//% size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); +//% msgSize += ComputeDict##VALUE_NAME##FieldSize(_values[i], kMapValueFieldNumber, valueDataType); //% [outputStream writeInt32NoTag:(int32_t)msgSize]; //% // Write the fields. -//% WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); -//% WriteDict##VALUE_NAME##Field(outputStream, _values[i], kMapValueFieldNumber, valueType); +//% WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); +//% WriteDict##VALUE_NAME##Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); //% } //% } //%} @@ -1149,14 +1150,14 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); +//% forKey:(GPBGenericValue *)key +//% keyDataType:(GPBDataType)keyDataType { +//% size_t msgSize = ComputeDict##KEY_NAME##FieldSize(key->value##KEY_NAME, kMapKeyFieldNumber, keyDataType); +//% msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); //% 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); +//% WriteDict##KEY_NAME##Field(outputStream, key->value##KEY_NAME, kMapKeyFieldNumber, keyDataType); +//% WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); //% [outputStream release]; //% return data; //%} @@ -1221,7 +1222,8 @@ void GPBDictionaryReadEntry(id mapDictionary, //% return NO; //%} //%PDDM-DEFINE BOOL_SET_GPBVALUE_FOR_KEY_POD(VALUE_NAME, VALUE_TYPE, VisP) -//%- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +//%- (void)setGPBGenericValue:(GPBGenericValue *)value +//% forGPBGenericValueKey:(GPBGenericValue *)key { //% int idx = (key->valueBool ? 1 : 0); //% _values[idx] = value->value##VALUE_NAME; //% _valueSet[idx] = YES; @@ -1401,7 +1403,8 @@ void GPBDictionaryReadEntry(id mapDictionary, //% 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 { +//%- (void)setGPBGenericValue:(GPBGenericValue *)value +//% forGPBGenericValueKey:(GPBGenericValue *)key { //% int idx = (key->valueBool ? 1 : 0); //% [_values[idx] release]; //% _values[idx] = [value->valueString retain]; @@ -1573,26 +1576,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -1601,16 +1604,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType); + WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueUInt32)]; } @@ -1778,26 +1782,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -1806,16 +1810,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueUInt32)]; } @@ -1983,26 +1988,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -2011,16 +2016,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueUInt32)]; } @@ -2188,26 +2194,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -2216,16 +2222,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType); + WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueUInt32)]; } @@ -2393,26 +2400,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -2421,16 +2428,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType); + WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueBool) forKey:@(key->valueUInt32)]; } @@ -2598,26 +2606,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -2626,16 +2634,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType); + WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueUInt32)]; } @@ -2803,26 +2812,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -2831,16 +2840,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType); + WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueUInt32)]; } @@ -3036,26 +3046,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -3064,28 +3074,29 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType { - size_t msgSize = ComputeDictUInt32FieldSize(key->valueUInt32, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum); + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictUInt32FieldSize(key->valueUInt32, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); NSMutableData *data = [NSMutableData dataWithLength:msgSize]; GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; - WriteDictUInt32Field(outputStream, key->valueUInt32, kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum); + WriteDictUInt32Field(outputStream, key->valueUInt32, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); [outputStream release]; return data; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueUInt32)]; } @@ -3315,26 +3326,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, id aValue, @@ -3343,16 +3354,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueType); + WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:value->valueString forKey:@(key->valueUInt32)]; } @@ -3520,26 +3532,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -3548,16 +3560,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType); - WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType); + WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueInt32)]; } @@ -3725,26 +3738,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -3753,16 +3766,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType); - WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueInt32)]; } @@ -3930,26 +3944,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -3958,16 +3972,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType); - WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueInt32)]; } @@ -4135,26 +4150,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -4163,16 +4178,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType); - WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType); + WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueInt32)]; } @@ -4340,26 +4356,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -4368,16 +4384,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType); - WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType); + WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueBool) forKey:@(key->valueInt32)]; } @@ -4545,26 +4562,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -4573,16 +4590,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType); - WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType); + WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueInt32)]; } @@ -4750,26 +4768,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -4778,16 +4796,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType); - WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType); + WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueInt32)]; } @@ -4983,26 +5002,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -5011,28 +5030,29 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType { - size_t msgSize = ComputeDictInt32FieldSize(key->valueInt32, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum); + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictInt32FieldSize(key->valueInt32, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); NSMutableData *data = [NSMutableData dataWithLength:msgSize]; GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; - WriteDictInt32Field(outputStream, key->valueInt32, kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum); + WriteDictInt32Field(outputStream, key->valueInt32, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); [outputStream release]; return data; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueInt32)]; } @@ -5262,26 +5282,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, id aValue, @@ -5290,16 +5310,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType); - WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueType); + WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType); + WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:value->valueString forKey:@(key->valueInt32)]; } @@ -5467,26 +5488,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -5495,16 +5516,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType); + WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueUInt64)]; } @@ -5672,26 +5694,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -5700,16 +5722,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueUInt64)]; } @@ -5877,26 +5900,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -5905,16 +5928,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueUInt64)]; } @@ -6082,26 +6106,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -6110,16 +6134,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType); + WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueUInt64)]; } @@ -6287,26 +6312,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -6315,16 +6340,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType); + WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueBool) forKey:@(key->valueUInt64)]; } @@ -6492,26 +6518,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -6520,16 +6546,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType); + WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueUInt64)]; } @@ -6697,26 +6724,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -6725,16 +6752,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType); + WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueUInt64)]; } @@ -6930,26 +6958,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -6958,28 +6986,29 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType { - size_t msgSize = ComputeDictUInt64FieldSize(key->valueUInt64, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum); + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictUInt64FieldSize(key->valueUInt64, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); NSMutableData *data = [NSMutableData dataWithLength:msgSize]; GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; - WriteDictUInt64Field(outputStream, key->valueUInt64, kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum); + WriteDictUInt64Field(outputStream, key->valueUInt64, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); [outputStream release]; return data; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueUInt64)]; } @@ -7209,26 +7238,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, id aValue, @@ -7237,16 +7266,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueType); + WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:value->valueString forKey:@(key->valueUInt64)]; } @@ -7414,26 +7444,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -7442,16 +7472,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType); - WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType); + WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueInt64)]; } @@ -7619,26 +7650,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -7647,16 +7678,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType); - WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueInt64)]; } @@ -7824,26 +7856,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -7852,16 +7884,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType); - WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueInt64)]; } @@ -8029,26 +8062,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -8057,16 +8090,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType); - WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType); + WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueInt64)]; } @@ -8234,26 +8268,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -8262,16 +8296,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType); - WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType); + WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueBool) forKey:@(key->valueInt64)]; } @@ -8439,26 +8474,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -8467,16 +8502,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType); - WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType); + WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueInt64)]; } @@ -8644,26 +8680,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -8672,16 +8708,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType); - WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType); + WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueInt64)]; } @@ -8877,26 +8914,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -8905,28 +8942,29 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType { - size_t msgSize = ComputeDictInt64FieldSize(key->valueInt64, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum); + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictInt64FieldSize(key->valueInt64, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); NSMutableData *data = [NSMutableData dataWithLength:msgSize]; GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; - WriteDictInt64Field(outputStream, key->valueInt64, kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum); + WriteDictInt64Field(outputStream, key->valueInt64, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); [outputStream release]; return data; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueInt64)]; } @@ -9156,26 +9194,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, id aValue, @@ -9184,16 +9222,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType); - WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueType); + WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:value->valueString forKey:@(key->valueInt64)]; } @@ -9361,26 +9400,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, @@ -9389,16 +9428,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType); - WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType); + WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt32) forKey:key->valueString]; } @@ -9566,26 +9606,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, @@ -9594,16 +9634,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType); - WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt32) forKey:key->valueString]; } @@ -9771,26 +9812,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, @@ -9799,16 +9840,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType); - WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt64) forKey:key->valueString]; } @@ -9976,26 +10018,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, @@ -10004,16 +10046,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType); - WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType); + WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt64) forKey:key->valueString]; } @@ -10181,26 +10224,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, @@ -10209,16 +10252,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType); - WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType); + WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueBool) forKey:key->valueString]; } @@ -10386,26 +10430,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, @@ -10414,16 +10458,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType); - WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType); + WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueFloat) forKey:key->valueString]; } @@ -10591,26 +10636,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, @@ -10619,16 +10664,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType); - WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType); + WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueDouble) forKey:key->valueString]; } @@ -10824,26 +10870,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __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); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, @@ -10852,28 +10898,29 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType { - size_t msgSize = ComputeDictStringFieldSize(key->valueString, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum); + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictStringFieldSize(key->valueString, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); NSMutableData *data = [NSMutableData dataWithLength:msgSize]; GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; - WriteDictStringField(outputStream, key->valueString, kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum); + WriteDictStringField(outputStream, key->valueString, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); [outputStream release]; return data; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueEnum) forKey:key->valueString]; } @@ -11104,7 +11151,8 @@ void GPBDictionaryReadEntry(id mapDictionary, return NO; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { int idx = (key->valueBool ? 1 : 0); _values[idx] = value->valueUInt32; _valueSet[idx] = YES; @@ -11131,37 +11179,37 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(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); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictUInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; } } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(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); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictUInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); - WriteDictUInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueType); + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictUInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); } } } @@ -11344,7 +11392,8 @@ void GPBDictionaryReadEntry(id mapDictionary, return NO; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { int idx = (key->valueBool ? 1 : 0); _values[idx] = value->valueInt32; _valueSet[idx] = YES; @@ -11371,37 +11420,37 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(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); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; } } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(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); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); - WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueType); + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); } } } @@ -11584,7 +11633,8 @@ void GPBDictionaryReadEntry(id mapDictionary, return NO; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { int idx = (key->valueBool ? 1 : 0); _values[idx] = value->valueUInt64; _valueSet[idx] = YES; @@ -11611,37 +11661,37 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(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); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictUInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; } } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(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); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictUInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); - WriteDictUInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueType); + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictUInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); } } } @@ -11824,7 +11874,8 @@ void GPBDictionaryReadEntry(id mapDictionary, return NO; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { int idx = (key->valueBool ? 1 : 0); _values[idx] = value->valueInt64; _valueSet[idx] = YES; @@ -11851,37 +11902,37 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(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); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; } } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(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); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); - WriteDictInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueType); + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); } } } @@ -12064,7 +12115,8 @@ void GPBDictionaryReadEntry(id mapDictionary, return NO; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { int idx = (key->valueBool ? 1 : 0); _values[idx] = value->valueBool; _valueSet[idx] = YES; @@ -12091,37 +12143,37 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(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); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictBoolFieldSize(_values[i], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; } } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(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); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictBoolFieldSize(_values[i], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); - WriteDictBoolField(outputStream, _values[i], kMapValueFieldNumber, valueType); + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictBoolField(outputStream, _values[i], kMapValueFieldNumber, valueDataType); } } } @@ -12304,7 +12356,8 @@ void GPBDictionaryReadEntry(id mapDictionary, return NO; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { int idx = (key->valueBool ? 1 : 0); _values[idx] = value->valueFloat; _valueSet[idx] = YES; @@ -12331,37 +12384,37 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(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); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictFloatFieldSize(_values[i], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; } } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(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); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictFloatFieldSize(_values[i], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); - WriteDictFloatField(outputStream, _values[i], kMapValueFieldNumber, valueType); + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictFloatField(outputStream, _values[i], kMapValueFieldNumber, valueDataType); } } } @@ -12544,7 +12597,8 @@ void GPBDictionaryReadEntry(id mapDictionary, return NO; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { int idx = (key->valueBool ? 1 : 0); _values[idx] = value->valueDouble; _valueSet[idx] = YES; @@ -12571,37 +12625,37 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(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); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictDoubleFieldSize(_values[i], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; } } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(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); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictDoubleFieldSize(_values[i], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); - WriteDictDoubleField(outputStream, _values[i], kMapValueFieldNumber, valueType); + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictDoubleField(outputStream, _values[i], kMapValueFieldNumber, valueDataType); } } } @@ -12772,7 +12826,8 @@ void GPBDictionaryReadEntry(id mapDictionary, return _values[key ? 1 : 0]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { int idx = (key->valueBool ? 1 : 0); [_values[idx] release]; _values[idx] = [value->valueString retain]; @@ -12820,37 +12875,37 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(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); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictObjectFieldSize(_values[i], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; } } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(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); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictObjectFieldSize(_values[i], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); - WriteDictObjectField(outputStream, _values[i], kMapValueFieldNumber, valueType); + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictObjectField(outputStream, _values[i], kMapValueFieldNumber, valueDataType); } } } @@ -13115,14 +13170,14 @@ void GPBDictionaryReadEntry(id mapDictionary, // 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); + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictBoolFieldSize(key->valueBool, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); NSMutableData *data = [NSMutableData dataWithLength:msgSize]; GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; - WriteDictBoolField(outputStream, key->valueBool, kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum); + WriteDictBoolField(outputStream, key->valueBool, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); [outputStream release]; return data; } @@ -13130,37 +13185,37 @@ void GPBDictionaryReadEntry(id mapDictionary, //%PDDM-EXPAND-END SERIAL_DATA_FOR_ENTRY_POD_Enum(Bool) - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(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); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; } } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(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); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); - WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueType); + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); } } } @@ -13174,7 +13229,8 @@ void GPBDictionaryReadEntry(id mapDictionary, } } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { int idx = (key->valueBool ? 1 : 0); _values[idx] = value->valueInt32; _valueSet[idx] = YES; diff --git a/objectivec/GPBDictionary_PackagePrivate.h b/objectivec/GPBDictionary_PackagePrivate.h index 9c3c5915..7b921e8e 100644 --- a/objectivec/GPBDictionary_PackagePrivate.h +++ b/objectivec/GPBDictionary_PackagePrivate.h @@ -41,7 +41,8 @@ - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key; - (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; @end @@ -75,8 +76,8 @@ //% //%PDDM-DEFINE EXTRA_DICTIONARY_PRIVATE_INTERFACES_Enum() //%- (NSData *)serializedDataForUnknownValue:(int32_t)value -//% forKey:(GPBValue *)key -//% keyType:(GPBType)keyType; +//% forKey:(GPBGenericValue *)key +//% keyDataType:(GPBDataType)keyDataType; //% //%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(UInt32) @@ -129,8 +130,8 @@ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType; + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; @end @interface GPBUInt32ObjectDictionary () <GPBDictionaryInternalsProtocol> { @@ -192,8 +193,8 @@ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType; + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; @end @interface GPBInt32ObjectDictionary () <GPBDictionaryInternalsProtocol> { @@ -255,8 +256,8 @@ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType; + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; @end @interface GPBUInt64ObjectDictionary () <GPBDictionaryInternalsProtocol> { @@ -318,8 +319,8 @@ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType; + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; @end @interface GPBInt64ObjectDictionary () <GPBDictionaryInternalsProtocol> { @@ -381,8 +382,8 @@ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType; + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; @end @interface GPBBoolObjectDictionary () <GPBDictionaryInternalsProtocol> { @@ -444,8 +445,8 @@ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType; + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; @end //%PDDM-EXPAND-END (6 expansions) diff --git a/objectivec/GPBExtensionField.m b/objectivec/GPBExtensionField.m deleted file mode 100644 index bbb36d7f..00000000 --- a/objectivec/GPBExtensionField.m +++ /dev/null @@ -1,525 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#import "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/GPBExtensionInternals.h b/objectivec/GPBExtensionInternals.h new file mode 100644 index 00000000..2b980aef --- /dev/null +++ b/objectivec/GPBExtensionInternals.h @@ -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. + +#import <Foundation/Foundation.h> + +#import "GPBDescriptor.h" + +@class GPBCodedInputStream; +@class GPBCodedOutputStream; +@class GPBExtensionRegistry; + +void GPBExtensionMergeFromInputStream(GPBExtensionDescriptor *extension, + BOOL isPackedOnStream, + GPBCodedInputStream *input, + GPBExtensionRegistry *extensionRegistry, + GPBMessage *message); + +size_t GPBComputeExtensionSerializedSizeIncludingTag( + GPBExtensionDescriptor *extension, id value); + +void GPBWriteExtensionValueToOutputStream(GPBExtensionDescriptor *extension, + id value, + GPBCodedOutputStream *output); diff --git a/objectivec/GPBExtensionInternals.m b/objectivec/GPBExtensionInternals.m new file mode 100644 index 00000000..634c3369 --- /dev/null +++ b/objectivec/GPBExtensionInternals.m @@ -0,0 +1,380 @@ +// 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 "GPBExtensionInternals.h" + +#import <objc/runtime.h> + +#import "GPBCodedInputStream_PackagePrivate.h" +#import "GPBCodedOutputStream.h" +#import "GPBDescriptor_PackagePrivate.h" +#import "GPBMessage_PackagePrivate.h" +#import "GPBUtilities_PackagePrivate.h" + +static id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension, + GPBCodedInputStream *input, + GPBExtensionRegistry *extensionRegistry, + GPBMessage *existingValue) + __attribute__((ns_returns_retained)); + +GPB_INLINE size_t DataTypeSize(GPBDataType dataType) { + switch (dataType) { + case GPBDataTypeBool: + return 1; + case GPBDataTypeFixed32: + case GPBDataTypeSFixed32: + case GPBDataTypeFloat: + return 4; + case GPBDataTypeFixed64: + case GPBDataTypeSFixed64: + case GPBDataTypeDouble: + return 8; + default: + return 0; + } +} + +static size_t ComputePBSerializedSizeNoTagOfObject(GPBDataType dataType, id object) { +#define FIELD_CASE(TYPE, ACCESSOR) \ + case GPBDataType##TYPE: \ + return GPBCompute##TYPE##SizeNoTag([(NSNumber *)object ACCESSOR]); +#define FIELD_CASE2(TYPE) \ + case GPBDataType##TYPE: \ + return GPBCompute##TYPE##SizeNoTag(object); + switch (dataType) { + 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(Bytes) + 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 GPBDataType##TYPE: \ + return GPBCompute##TYPE##Size(description->fieldNumber, \ + [(NSNumber *)object ACCESSOR]); +#define FIELD_CASE2(TYPE) \ + case GPBDataType##TYPE: \ + return GPBCompute##TYPE##Size(description->fieldNumber, object); + switch (description->dataType) { + 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(Bytes) + FIELD_CASE2(String) + FIELD_CASE2(Group) + case GPBDataTypeMessage: + if (GPBExtensionIsWireFormat(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 (GPBExtensionIsPacked(description)) { + size_t size = 0; + size_t typeSize = DataTypeSize(description->dataType); + if (typeSize != 0) { + size = values.count * typeSize; + } else { + for (id value in values) { + size += + ComputePBSerializedSizeNoTagOfObject(description->dataType, 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 GPBDataType##TYPE: \ + [output write##TYPE:description->fieldNumber \ + value:[(NSNumber *)object ACCESSOR]]; \ + return; +#define FIELD_CASE2(TYPE) \ + case GPBDataType##TYPE: \ + [output write##TYPE:description->fieldNumber value:object]; \ + return; + switch (description->dataType) { + 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(Bytes) + FIELD_CASE2(String) + FIELD_CASE2(Group) + case GPBDataTypeMessage: + if (GPBExtensionIsWireFormat(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 GPBDataType##TYPE: \ + [output write##TYPE##NoTag:[(NSNumber *)object ACCESSOR]]; \ + return; +#define FIELD_CASE2(TYPE) \ + case GPBDataType##TYPE: \ + [output write##TYPE##NoTag:object]; \ + return; + switch (description->dataType) { + 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(Bytes) + FIELD_CASE2(String) + FIELD_CASE2(Message) + case GPBDataTypeGroup: + [output writeGroupNoTag:description->fieldNumber value:object]; + return; + } +#undef FIELD_CASE +#undef FIELD_CASE2 +} + +static void WriteArrayIncludingTagsToCodedOutputStream( + NSArray *values, GPBExtensionDescription *description, + GPBCodedOutputStream *output) { + if (GPBExtensionIsPacked(description)) { + [output writeTag:description->fieldNumber + format:GPBWireFormatLengthDelimited]; + size_t dataSize = 0; + size_t typeSize = DataTypeSize(description->dataType); + if (typeSize != 0) { + dataSize = values.count * typeSize; + } else { + for (id value in values) { + dataSize += + ComputePBSerializedSizeNoTagOfObject(description->dataType, value); + } + } + [output writeRawVarintSizeTAs32:dataSize]; + for (id value in values) { + WriteObjectNoTagToCodedOutputStream(value, description, output); + } + } else { + for (id value in values) { + WriteObjectIncludingTagToCodedOutputStream(value, description, output); + } + } +} + +void GPBExtensionMergeFromInputStream(GPBExtensionDescriptor *extension, + BOOL isPackedOnStream, + GPBCodedInputStream *input, + GPBExtensionRegistry *extensionRegistry, + GPBMessage *message) { + GPBExtensionDescription *description = extension->description_; + GPBCodedInputStreamState *state = &input->state_; + if (isPackedOnStream) { + NSCAssert(GPBExtensionIsRepeated(description), + @"How was it packed if it isn't repeated?"); + int32_t length = GPBCodedInputStreamReadInt32(state); + size_t limit = GPBCodedInputStreamPushLimit(state, length); + while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { + id value = NewSingleValueFromInputStream(extension, + input, + extensionRegistry, + nil); + [message addExtension:extension value:value]; + [value release]; + } + GPBCodedInputStreamPopLimit(state, limit); + } else { + id existingValue = nil; + BOOL isRepeated = GPBExtensionIsRepeated(description); + if (!isRepeated && GPBDataTypeIsMessage(description->dataType)) { + existingValue = [message getExistingExtension:extension]; + } + id value = NewSingleValueFromInputStream(extension, + input, + extensionRegistry, + existingValue); + if (isRepeated) { + [message addExtension:extension value:value]; + } else { + [message setExtension:extension value:value]; + } + [value release]; + } +} + +void GPBWriteExtensionValueToOutputStream(GPBExtensionDescriptor *extension, + id value, + GPBCodedOutputStream *output) { + GPBExtensionDescription *description = extension->description_; + if (GPBExtensionIsRepeated(description)) { + WriteArrayIncludingTagsToCodedOutputStream(value, description, output); + } else { + WriteObjectIncludingTagToCodedOutputStream(value, description, output); + } +} + +size_t GPBComputeExtensionSerializedSizeIncludingTag( + GPBExtensionDescriptor *extension, id value) { + GPBExtensionDescription *description = extension->description_; + if (GPBExtensionIsRepeated(description)) { + return ComputeSerializedSizeIncludingTagOfArray(description, value); + } else { + return ComputeSerializedSizeIncludingTagOfObject(description, value); + } +} + +// Note that this returns a retained value intentionally. +static id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension, + GPBCodedInputStream *input, + GPBExtensionRegistry *extensionRegistry, + GPBMessage *existingValue) { + GPBExtensionDescription *description = extension->description_; + GPBCodedInputStreamState *state = &input->state_; + switch (description->dataType) { + case GPBDataTypeBool: return [[NSNumber alloc] initWithBool:GPBCodedInputStreamReadBool(state)]; + case GPBDataTypeFixed32: return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadFixed32(state)]; + case GPBDataTypeSFixed32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSFixed32(state)]; + case GPBDataTypeFloat: return [[NSNumber alloc] initWithFloat:GPBCodedInputStreamReadFloat(state)]; + case GPBDataTypeFixed64: return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadFixed64(state)]; + case GPBDataTypeSFixed64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSFixed64(state)]; + case GPBDataTypeDouble: return [[NSNumber alloc] initWithDouble:GPBCodedInputStreamReadDouble(state)]; + case GPBDataTypeInt32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadInt32(state)]; + case GPBDataTypeInt64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadInt64(state)]; + case GPBDataTypeSInt32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSInt32(state)]; + case GPBDataTypeSInt64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSInt64(state)]; + case GPBDataTypeUInt32: return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadUInt32(state)]; + case GPBDataTypeUInt64: return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadUInt64(state)]; + case GPBDataTypeBytes: return GPBCodedInputStreamReadRetainedBytes(state); + case GPBDataTypeString: return GPBCodedInputStreamReadRetainedString(state); + case GPBDataTypeEnum: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadEnum(state)]; + case GPBDataTypeGroup: + case GPBDataTypeMessage: { + GPBMessage *message; + if (existingValue) { + message = [existingValue retain]; + } else { + GPBDescriptor *decriptor = [extension.msgClass descriptor]; + message = [[decriptor.messageClass alloc] init]; + } + + if (description->dataType == GPBDataTypeGroup) { + [input readGroup:description->fieldNumber + message:message + extensionRegistry:extensionRegistry]; + } else { + // description->dataType == GPBDataTypeMessage + if (GPBExtensionIsWireFormat(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; +} diff --git a/objectivec/GPBExtensionRegistry.h b/objectivec/GPBExtensionRegistry.h index e382971c..0363c70a 100644 --- a/objectivec/GPBExtensionRegistry.h +++ b/objectivec/GPBExtensionRegistry.h @@ -31,7 +31,9 @@ #import <Foundation/Foundation.h> @class GPBDescriptor; -@class GPBExtensionField; +@class GPBExtensionDescriptor; + +NS_ASSUME_NONNULL_BEGIN // A table of known extensions, searchable by name or field number. When // parsing a protocol message that might have extensions, you must provide an @@ -54,10 +56,12 @@ // @interface GPBExtensionRegistry : NSObject<NSCopying> -- (void)addExtension:(GPBExtensionField *)extension; +- (void)addExtension:(GPBExtensionDescriptor *)extension; - (void)addExtensions:(GPBExtensionRegistry *)registry; -- (GPBExtensionField *)getExtension:(GPBDescriptor *)containingType - fieldNumber:(NSInteger)fieldNumber; +- (nullable GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor + fieldNumber:(NSInteger)fieldNumber; @end + +NS_ASSUME_NONNULL_END diff --git a/objectivec/GPBExtensionRegistry.m b/objectivec/GPBExtensionRegistry.m index 4f234f55..df61a17b 100644 --- a/objectivec/GPBExtensionRegistry.m +++ b/objectivec/GPBExtensionRegistry.m @@ -32,7 +32,6 @@ #import "GPBBootstrap.h" #import "GPBDescriptor.h" -#import "GPBExtensionField.h" @implementation GPBExtensionRegistry { // TODO(dmaclach): Reimplement with CFDictionaries that don't use @@ -60,31 +59,34 @@ return result; } -- (NSMutableDictionary *)extensionMapForContainingType: - (GPBDescriptor *)containingType { +- (NSMutableDictionary *)extensionMapForContainingMessageClass: + (Class)containingMessageClass { NSMutableDictionary *extensionMap = - [mutableClassMap_ objectForKey:containingType]; + [mutableClassMap_ objectForKey:containingMessageClass]; if (extensionMap == nil) { extensionMap = [NSMutableDictionary dictionary]; - [mutableClassMap_ setObject:extensionMap forKey:containingType]; + [mutableClassMap_ setObject:extensionMap + forKey:(id<NSCopying>)containingMessageClass]; } return extensionMap; } -- (void)addExtension:(GPBExtensionField *)extension { +- (void)addExtension:(GPBExtensionDescriptor *)extension { if (extension == nil) { return; } - GPBDescriptor *containingType = [extension containingType]; + Class containingMessageClass = extension.containingMessageClass; NSMutableDictionary *extensionMap = - [self extensionMapForContainingType:containingType]; - [extensionMap setObject:extension forKey:@([extension fieldNumber])]; + [self extensionMapForContainingMessageClass:containingMessageClass]; + [extensionMap setObject:extension forKey:@(extension.fieldNumber)]; } -- (GPBExtensionField *)getExtension:(GPBDescriptor *)containingType - fieldNumber:(NSInteger)fieldNumber { - NSDictionary *extensionMap = [mutableClassMap_ objectForKey:containingType]; +- (GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor + fieldNumber:(NSInteger)fieldNumber { + Class messageClass = descriptor.messageClass; + NSDictionary *extensionMap = + [mutableClassMap_ objectForKey:messageClass]; return [extensionMap objectForKey:@(fieldNumber)]; } @@ -94,11 +96,11 @@ return; } NSMutableDictionary *otherClassMap = registry->mutableClassMap_; - for (GPBDescriptor *containingType in otherClassMap) { + for (Class containingMessageClass in otherClassMap) { NSMutableDictionary *extensionMap = - [self extensionMapForContainingType:containingType]; + [self extensionMapForContainingMessageClass:containingMessageClass]; NSMutableDictionary *otherExtensionMap = - [registry extensionMapForContainingType:containingType]; + [registry extensionMapForContainingMessageClass:containingMessageClass]; [extensionMap addEntriesFromDictionary:otherExtensionMap]; } } diff --git a/objectivec/GPBMessage.h b/objectivec/GPBMessage.h index 1c6c091d..d4c2fccf 100644 --- a/objectivec/GPBMessage.h +++ b/objectivec/GPBMessage.h @@ -35,11 +35,13 @@ @class GPBDescriptor; @class GPBCodedInputStream; @class GPBCodedOutputStream; -@class GPBExtensionField; +@class GPBExtensionDescriptor; @class GPBExtensionRegistry; @class GPBFieldDescriptor; @class GPBUnknownFieldSet; +NS_ASSUME_NONNULL_BEGIN + CF_EXTERN_C_BEGIN // NSError domain used for errors. @@ -66,7 +68,7 @@ CF_EXTERN_C_END // The main cases are methods that take no arguments, or setFoo:/hasFoo: type // methods. -@property(nonatomic, readonly) GPBUnknownFieldSet *unknownFields; +@property(nonatomic, copy, nullable) GPBUnknownFieldSet *unknownFields; // Are all required fields in the message and all embedded messages set. @property(nonatomic, readonly, getter=isInitialized) BOOL initialized; @@ -80,18 +82,18 @@ CF_EXTERN_C_END // if one is missing, the parse will fail (returning nil, filling in errorPtr). + (instancetype)parseFromData:(NSData *)data error:(NSError **)errorPtr; + (instancetype)parseFromData:(NSData *)data - extensionRegistry:(GPBExtensionRegistry *)extensionRegistry + extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry error:(NSError **)errorPtr; + (instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input extensionRegistry: - (GPBExtensionRegistry *)extensionRegistry + (nullable GPBExtensionRegistry *)extensionRegistry error:(NSError **)errorPtr; // Create a message based on delimited input. If there is a data parse // error, nil is returned and if not NULL, errorPtr is filled in. + (instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input extensionRegistry: - (GPBExtensionRegistry *)extensionRegistry + (nullable GPBExtensionRegistry *)extensionRegistry error:(NSError **)errorPtr; // If there is a data parse error, nil is returned and if not NULL, errorPtr is @@ -100,11 +102,11 @@ CF_EXTERN_C_END // if one is missing, the parse will fail (returning nil, filling in errorPtr). - (instancetype)initWithData:(NSData *)data error:(NSError **)errorPtr; - (instancetype)initWithData:(NSData *)data - extensionRegistry:(GPBExtensionRegistry *)extensionRegistry + extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry error:(NSError **)errorPtr; - (instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input extensionRegistry: - (GPBExtensionRegistry *)extensionRegistry + (nullable GPBExtensionRegistry *)extensionRegistry error:(NSError **)errorPtr; // Serializes the message and writes it to output. @@ -121,11 +123,11 @@ CF_EXTERN_C_END // while generating the data, nil is returned. // NOTE: In DEBUG ONLY, the message is also checked for all required field, // if one is missing, nil will be returned. -- (NSData *)data; +- (nullable 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; +- (nullable 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: @@ -148,16 +150,14 @@ CF_EXTERN_C_END // Extensions use boxed values (NSNumbers) for PODs, NSMutableArrays for // repeated. If the extension is a Message one will be auto created for you // and returned similar to fields. -- (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 +- (BOOL)hasExtension:(GPBExtensionDescriptor *)extension; +- (nullable id)getExtension:(GPBExtensionDescriptor *)extension; +- (void)setExtension:(GPBExtensionDescriptor *)extension value:(nullable id)value; +- (void)addExtension:(GPBExtensionDescriptor *)extension value:(id)value; +- (void)setExtension:(GPBExtensionDescriptor *)extension index:(NSUInteger)index value:(id)value; -- (void)clearExtension:(GPBExtensionField *)extension; - -- (void)setUnknownFields:(GPBUnknownFieldSet *)unknownFields; +- (void)clearExtension:(GPBExtensionDescriptor *)extension; // Resets all fields to their default values. - (void)clear; @@ -166,10 +166,12 @@ CF_EXTERN_C_END // message. // NOTE: This will throw if there is an error parsing the data. - (void)mergeFromData:(NSData *)data - extensionRegistry:(GPBExtensionRegistry *)extensionRegistry; + extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry; // Merges the fields from another message (of the same type) into this // message. - (void)mergeFrom:(GPBMessage *)other; @end + +NS_ASSUME_NONNULL_END diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m index bd3235f1..c655edd3 100644 --- a/objectivec/GPBMessage.m +++ b/objectivec/GPBMessage.m @@ -38,7 +38,7 @@ #import "GPBCodedOutputStream.h" #import "GPBDescriptor_PackagePrivate.h" #import "GPBDictionary_PackagePrivate.h" -#import "GPBExtensionField_PackagePrivate.h" +#import "GPBExtensionInternals.h" #import "GPBExtensionRegistry.h" #import "GPBRootObject_PackagePrivate.h" #import "GPBUnknownFieldSet_PackagePrivate.h" @@ -54,6 +54,13 @@ NSString *const GPBExceptionMessageKey = static NSString *const kGPBDataCoderKey = @"GPBData"; +#ifndef _GPBCompileAssert +#define _GPBCompileAssertSymbolInner(line, msg) _GPBCompileAssert ## line ## __ ## msg +#define _GPBCompileAssertSymbol(line, msg) _GPBCompileAssertSymbolInner(line, msg) +#define _GPBCompileAssert(test, msg) \ + typedef char _GPBCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ] +#endif // _GPBCompileAssert + // // PLEASE REMEMBER: // @@ -73,7 +80,7 @@ static NSString *const kGPBDataCoderKey = @"GPBData"; // mutated, we can inform the creator to make our field visible. GPBMessage *autocreator_; GPBFieldDescriptor *autocreatorField_; - GPBExtensionField *autocreatorExtension_; + GPBExtensionDescriptor *autocreatorExtension_; } @end @@ -110,13 +117,14 @@ static NSError *MessageErrorWithReason(NSInteger code, NSString *reason) { } -static void CheckExtension(GPBMessage *self, GPBExtensionField *extension) { - if ([[self class] descriptor] != [extension containingType]) { +static void CheckExtension(GPBMessage *self, + GPBExtensionDescriptor *extension) { + if ([self class] != extension.containingMessageClass) { [NSException raise:NSInvalidArgumentException format:@"Extension %@ used on wrong class (%@ instead of %@)", - extension.descriptor.singletonName, - [[self class] descriptor].name, [extension containingType].name]; + extension.singletonName, + [self class], extension.containingMessageClass]; } } @@ -128,12 +136,11 @@ static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, 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); + for (GPBExtensionDescriptor *extension in extensionMap) { + id value = [extensionMap objectForKey:extension]; + BOOL isMessageExtension = GPBExtensionIsMessage(extension); - if ([field isRepeated]) { + if (extension.repeated) { if (isMessageExtension) { NSMutableArray *list = [[NSMutableArray alloc] initWithCapacity:[value count]]; @@ -142,20 +149,20 @@ static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, [list addObject:copiedValue]; [copiedValue release]; } - [result setObject:list forKey:field]; + [result setObject:list forKey:extension]; [list release]; } else { NSMutableArray *copiedValue = [value mutableCopyWithZone:zone]; - [result setObject:copiedValue forKey:field]; + [result setObject:copiedValue forKey:extension]; [copiedValue release]; } } else { if (isMessageExtension) { GPBMessage *copiedValue = [value copyWithZone:zone]; - [result setObject:copiedValue forKey:field]; + [result setObject:copiedValue forKey:extension]; [copiedValue release]; } else { - [result setObject:value forKey:field]; + [result setObject:value forKey:extension]; } } } @@ -166,45 +173,45 @@ static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, static id CreateArrayForField(GPBFieldDescriptor *field, GPBMessage *autocreator) { id result; - GPBType fieldDataType = GPBGetFieldType(field); + GPBDataType fieldDataType = GPBGetFieldDataType(field); switch (fieldDataType) { - case GPBTypeBool: + case GPBDataTypeBool: result = [[GPBBoolArray alloc] init]; break; - case GPBTypeFixed32: - case GPBTypeUInt32: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: result = [[GPBUInt32Array alloc] init]; break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: result = [[GPBInt32Array alloc] init]; break; - case GPBTypeFixed64: - case GPBTypeUInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: result = [[GPBUInt64Array alloc] init]; break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: result = [[GPBInt64Array alloc] init]; break; - case GPBTypeFloat: + case GPBDataTypeFloat: result = [[GPBFloatArray alloc] init]; break; - case GPBTypeDouble: + case GPBDataTypeDouble: result = [[GPBDoubleArray alloc] init]; break; - case GPBTypeEnum: + case GPBDataTypeEnum: result = [[GPBEnumArray alloc] initWithValidationFunction:field.enumDescriptor.enumVerifier]; break; - case GPBTypeData: - case GPBTypeGroup: - case GPBTypeMessage: - case GPBTypeString: + case GPBDataTypeBytes: + case GPBDataTypeGroup: + case GPBDataTypeMessage: + case GPBDataTypeString: if (autocreator) { result = [[GPBAutocreatedArray alloc] init]; } else { @@ -214,7 +221,7 @@ static id CreateArrayForField(GPBFieldDescriptor *field, } if (autocreator) { - if (GPBTypeIsObject(fieldDataType)) { + if (GPBDataTypeIsObject(fieldDataType)) { GPBAutocreatedArray *autoArray = result; autoArray->_autocreator = autocreator; } else { @@ -229,290 +236,291 @@ static id CreateArrayForField(GPBFieldDescriptor *field, static id CreateMapForField(GPBFieldDescriptor *field, GPBMessage *autocreator) { id result; - GPBType keyType = field.mapKeyType; - GPBType valueType = GPBGetFieldType(field); - switch (keyType) { - case GPBTypeBool: - switch (valueType) { - case GPBTypeBool: + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + switch (keyDataType) { + case GPBDataTypeBool: + switch (valueDataType) { + case GPBDataTypeBool: result = [[GPBBoolBoolDictionary alloc] init]; break; - case GPBTypeFixed32: - case GPBTypeUInt32: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: result = [[GPBBoolUInt32Dictionary alloc] init]; break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: result = [[GPBBoolInt32Dictionary alloc] init]; break; - case GPBTypeFixed64: - case GPBTypeUInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: result = [[GPBBoolUInt64Dictionary alloc] init]; break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: result = [[GPBBoolInt64Dictionary alloc] init]; break; - case GPBTypeFloat: + case GPBDataTypeFloat: result = [[GPBBoolFloatDictionary alloc] init]; break; - case GPBTypeDouble: + case GPBDataTypeDouble: result = [[GPBBoolDoubleDictionary alloc] init]; break; - case GPBTypeEnum: + case GPBDataTypeEnum: result = [[GPBBoolEnumDictionary alloc] initWithValidationFunction:field.enumDescriptor.enumVerifier]; break; - case GPBTypeData: - case GPBTypeMessage: - case GPBTypeString: + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: result = [[GPBBoolObjectDictionary alloc] init]; break; - case GPBTypeGroup: + case GPBDataTypeGroup: NSCAssert(NO, @"shouldn't happen"); return nil; } break; - case GPBTypeFixed32: - case GPBTypeUInt32: - switch (valueType) { - case GPBTypeBool: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + switch (valueDataType) { + case GPBDataTypeBool: result = [[GPBUInt32BoolDictionary alloc] init]; break; - case GPBTypeFixed32: - case GPBTypeUInt32: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: result = [[GPBUInt32UInt32Dictionary alloc] init]; break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: result = [[GPBUInt32Int32Dictionary alloc] init]; break; - case GPBTypeFixed64: - case GPBTypeUInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: result = [[GPBUInt32UInt64Dictionary alloc] init]; break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: result = [[GPBUInt32Int64Dictionary alloc] init]; break; - case GPBTypeFloat: + case GPBDataTypeFloat: result = [[GPBUInt32FloatDictionary alloc] init]; break; - case GPBTypeDouble: + case GPBDataTypeDouble: result = [[GPBUInt32DoubleDictionary alloc] init]; break; - case GPBTypeEnum: + case GPBDataTypeEnum: result = [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:field.enumDescriptor.enumVerifier]; break; - case GPBTypeData: - case GPBTypeMessage: - case GPBTypeString: + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: result = [[GPBUInt32ObjectDictionary alloc] init]; break; - case GPBTypeGroup: + case GPBDataTypeGroup: NSCAssert(NO, @"shouldn't happen"); return nil; } break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: - switch (valueType) { - case GPBTypeBool: + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + switch (valueDataType) { + case GPBDataTypeBool: result = [[GPBInt32BoolDictionary alloc] init]; break; - case GPBTypeFixed32: - case GPBTypeUInt32: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: result = [[GPBInt32UInt32Dictionary alloc] init]; break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: result = [[GPBInt32Int32Dictionary alloc] init]; break; - case GPBTypeFixed64: - case GPBTypeUInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: result = [[GPBInt32UInt64Dictionary alloc] init]; break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: result = [[GPBInt32Int64Dictionary alloc] init]; break; - case GPBTypeFloat: + case GPBDataTypeFloat: result = [[GPBInt32FloatDictionary alloc] init]; break; - case GPBTypeDouble: + case GPBDataTypeDouble: result = [[GPBInt32DoubleDictionary alloc] init]; break; - case GPBTypeEnum: + case GPBDataTypeEnum: result = [[GPBInt32EnumDictionary alloc] initWithValidationFunction:field.enumDescriptor.enumVerifier]; break; - case GPBTypeData: - case GPBTypeMessage: - case GPBTypeString: + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: result = [[GPBInt32ObjectDictionary alloc] init]; break; - case GPBTypeGroup: + case GPBDataTypeGroup: NSCAssert(NO, @"shouldn't happen"); return nil; } break; - case GPBTypeFixed64: - case GPBTypeUInt64: - switch (valueType) { - case GPBTypeBool: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + switch (valueDataType) { + case GPBDataTypeBool: result = [[GPBUInt64BoolDictionary alloc] init]; break; - case GPBTypeFixed32: - case GPBTypeUInt32: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: result = [[GPBUInt64UInt32Dictionary alloc] init]; break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: result = [[GPBUInt64Int32Dictionary alloc] init]; break; - case GPBTypeFixed64: - case GPBTypeUInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: result = [[GPBUInt64UInt64Dictionary alloc] init]; break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: result = [[GPBUInt64Int64Dictionary alloc] init]; break; - case GPBTypeFloat: + case GPBDataTypeFloat: result = [[GPBUInt64FloatDictionary alloc] init]; break; - case GPBTypeDouble: + case GPBDataTypeDouble: result = [[GPBUInt64DoubleDictionary alloc] init]; break; - case GPBTypeEnum: + case GPBDataTypeEnum: result = [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:field.enumDescriptor.enumVerifier]; break; - case GPBTypeData: - case GPBTypeMessage: - case GPBTypeString: + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: result = [[GPBUInt64ObjectDictionary alloc] init]; break; - case GPBTypeGroup: + case GPBDataTypeGroup: NSCAssert(NO, @"shouldn't happen"); return nil; } break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: - switch (valueType) { - case GPBTypeBool: + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + switch (valueDataType) { + case GPBDataTypeBool: result = [[GPBInt64BoolDictionary alloc] init]; break; - case GPBTypeFixed32: - case GPBTypeUInt32: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: result = [[GPBInt64UInt32Dictionary alloc] init]; break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: result = [[GPBInt64Int32Dictionary alloc] init]; break; - case GPBTypeFixed64: - case GPBTypeUInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: result = [[GPBInt64UInt64Dictionary alloc] init]; break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: result = [[GPBInt64Int64Dictionary alloc] init]; break; - case GPBTypeFloat: + case GPBDataTypeFloat: result = [[GPBInt64FloatDictionary alloc] init]; break; - case GPBTypeDouble: + case GPBDataTypeDouble: result = [[GPBInt64DoubleDictionary alloc] init]; break; - case GPBTypeEnum: + case GPBDataTypeEnum: result = [[GPBInt64EnumDictionary alloc] initWithValidationFunction:field.enumDescriptor.enumVerifier]; break; - case GPBTypeData: - case GPBTypeMessage: - case GPBTypeString: + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: result = [[GPBInt64ObjectDictionary alloc] init]; break; - case GPBTypeGroup: + case GPBDataTypeGroup: NSCAssert(NO, @"shouldn't happen"); return nil; } break; - case GPBTypeString: - switch (valueType) { - case GPBTypeBool: + case GPBDataTypeString: + switch (valueDataType) { + case GPBDataTypeBool: result = [[GPBStringBoolDictionary alloc] init]; break; - case GPBTypeFixed32: - case GPBTypeUInt32: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: result = [[GPBStringUInt32Dictionary alloc] init]; break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: result = [[GPBStringInt32Dictionary alloc] init]; break; - case GPBTypeFixed64: - case GPBTypeUInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: result = [[GPBStringUInt64Dictionary alloc] init]; break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: result = [[GPBStringInt64Dictionary alloc] init]; break; - case GPBTypeFloat: + case GPBDataTypeFloat: result = [[GPBStringFloatDictionary alloc] init]; break; - case GPBTypeDouble: + case GPBDataTypeDouble: result = [[GPBStringDoubleDictionary alloc] init]; break; - case GPBTypeEnum: + case GPBDataTypeEnum: result = [[GPBStringEnumDictionary alloc] initWithValidationFunction:field.enumDescriptor.enumVerifier]; break; - case GPBTypeData: - case GPBTypeMessage: - case GPBTypeString: + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: if (autocreator) { result = [[GPBAutocreatedDictionary alloc] init]; } else { result = [[NSMutableDictionary alloc] init]; } break; - case GPBTypeGroup: + case GPBDataTypeGroup: NSCAssert(NO, @"shouldn't happen"); return nil; } break; - case GPBTypeFloat: - case GPBTypeDouble: - case GPBTypeEnum: - case GPBTypeData: - case GPBTypeGroup: - case GPBTypeMessage: + case GPBDataTypeFloat: + case GPBDataTypeDouble: + case GPBDataTypeEnum: + case GPBDataTypeBytes: + case GPBDataTypeGroup: + case GPBDataTypeMessage: NSCAssert(NO, @"shouldn't happen"); return nil; } if (autocreator) { - if ((keyType == GPBTypeString) && GPBTypeIsObject(valueType)) { + if ((keyDataType == GPBDataTypeString) && + GPBDataTypeIsObject(valueDataType)) { GPBAutocreatedDictionary *autoDict = result; autoDict->_autocreator = autocreator; } else { @@ -608,11 +616,12 @@ GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass, } static GPBMessage *CreateMessageWithAutocreatorForExtension( - Class msgClass, GPBMessage *autocreator, GPBExtensionField *extension) + Class msgClass, GPBMessage *autocreator, GPBExtensionDescriptor *extension) __attribute__((ns_returns_retained)); static GPBMessage *CreateMessageWithAutocreatorForExtension( - Class msgClass, GPBMessage *autocreator, GPBExtensionField *extension) { + Class msgClass, GPBMessage *autocreator, + GPBExtensionDescriptor *extension) { GPBMessage *message = [[msgClass alloc] init]; message->autocreator_ = autocreator; message->autocreatorExtension_ = [extension retain]; @@ -647,7 +656,7 @@ void GPBAutocreatedArrayModified(GPBMessage *self, id array) { if (field.fieldType == GPBFieldTypeRepeated) { id curArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field); if (curArray == array) { - if (GPBFieldTypeIsObject(field)) { + if (GPBFieldDataTypeIsObject(field)) { GPBAutocreatedArray *autoArray = array; autoArray->_autocreator = nil; } else { @@ -669,8 +678,8 @@ void GPBAutocreatedDictionaryModified(GPBMessage *self, id dictionary) { if (field.fieldType == GPBFieldTypeMap) { id curDict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); if (curDict == dictionary) { - if ((field.mapKeyType == GPBTypeString) && - GPBFieldTypeIsObject(field)) { + if ((field.mapKeyDataType == GPBDataTypeString) && + GPBFieldDataTypeIsObject(field)) { GPBAutocreatedDictionary *autoDict = dictionary; autoDict->_autocreator = nil; } else { @@ -812,6 +821,9 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { if ((self = [self init])) { @try { [self mergeFromData:data extensionRegistry:extensionRegistry]; + if (errorPtr) { + *errorPtr = nil; + } } @catch (NSException *exception) { [self release]; @@ -841,6 +853,9 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { if ((self = [self init])) { @try { [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry]; + if (errorPtr) { + *errorPtr = nil; + } } @catch (NSException *exception) { [self release]; @@ -885,7 +900,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { // 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 (GPBFieldDataTypeIsMessage(field)) { if (field.fieldType == GPBFieldTypeRepeated) { NSArray *existingArray = (NSArray *)value; NSMutableArray *newArray = @@ -897,7 +912,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { [copiedMsg release]; } } else { - if (field.mapKeyType == GPBTypeString) { + if (field.mapKeyDataType == GPBDataTypeString) { // Map is an NSDictionary. NSDictionary *existingDict = value; NSMutableDictionary *newDict = [[NSMutableDictionary alloc] @@ -921,7 +936,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } else { // Not messages (but is a map/array)... if (field.fieldType == GPBFieldTypeRepeated) { - if (GPBFieldTypeIsObject(field)) { + if (GPBFieldDataTypeIsObject(field)) { // NSArray newValue = [value mutableCopyWithZone:zone]; } else { @@ -929,7 +944,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { newValue = [value copyWithZone:zone]; } } else { - if (field.mapKeyType == GPBTypeString) { + if (field.mapKeyDataType == GPBDataTypeString) { // NSDictionary newValue = [value mutableCopyWithZone:zone]; } else { @@ -946,7 +961,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue, syntax); } - } else if (GPBFieldTypeIsMessage(field)) { + } else if (GPBFieldDataTypeIsMessage(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). @@ -963,7 +978,8 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { id *typePtr = (id *)&storage[field->description_->offset]; *typePtr = NULL; } - } else if (GPBFieldTypeIsObject(field) && GPBGetHasIvarField(self, field)) { + } else if (GPBFieldDataTypeIsObject(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]; @@ -973,7 +989,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue, syntax); } else { - // memcpy took care of the rest of the primative fields if they were set. + // memcpy took care of the rest of the primitive fields if they were set. } } // for (field in descriptor->fields_) } @@ -1000,7 +1016,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { id arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field); if (arrayOrMap) { if (field.fieldType == GPBFieldTypeRepeated) { - if (GPBFieldTypeIsObject(field)) { + if (GPBFieldDataTypeIsObject(field)) { GPBAutocreatedArray *autoArray = arrayOrMap; if (autoArray->_autocreator == self) { autoArray->_autocreator = nil; @@ -1013,8 +1029,8 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } } } else { - if ((field.mapKeyType == GPBTypeString) && - GPBFieldTypeIsObject(field)) { + if ((field.mapKeyDataType == GPBDataTypeString) && + GPBFieldDataTypeIsObject(field)) { GPBAutocreatedDictionary *autoDict = arrayOrMap; if (autoDict->_autocreator == self) { autoDict->_autocreator = nil; @@ -1029,11 +1045,12 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } [arrayOrMap release]; } - } else if (GPBFieldTypeIsMessage(field)) { + } else if (GPBFieldDataTypeIsMessage(field)) { GPBClearAutocreatedMessageIvarWithField(self, field); GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); [value release]; - } else if (GPBFieldTypeIsObject(field) && GPBGetHasIvarField(self, field)) { + } else if (GPBFieldDataTypeIsObject(field) && + GPBGetHasIvarField(self, field)) { id value = GPBGetObjectIvarWithField(self, field); [value release]; } @@ -1076,11 +1093,11 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { return NO; } } - if (GPBFieldTypeIsMessage(field)) { + if (GPBFieldDataTypeIsMessage(field)) { GPBFieldType fieldType = field.fieldType; if (fieldType == GPBFieldTypeSingle) { if (field.isRequired) { - GPBMessage *message = GPBGetMessageIvarWithField(self, field); + GPBMessage *message = GPBGetMessageMessageField(self, field); if (!message.initialized) { return NO; } @@ -1089,7 +1106,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { @"%@: Single message field %@ not required or optional?", [self class], field.name); if (GPBGetHasIvarField(self, field)) { - GPBMessage *message = GPBGetMessageIvarWithField(self, field); + GPBMessage *message = GPBGetMessageMessageField(self, field); if (!message.initialized) { return NO; } @@ -1103,7 +1120,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } } } else { // fieldType == GPBFieldTypeMap - if (field.mapKeyType == GPBTypeString) { + if (field.mapKeyDataType == GPBDataTypeString) { NSDictionary *map = GPBGetObjectIvarWithFieldNoAutocreate(self, field); if (map && !GPBDictionaryIsInitializedInternalHelper(map, field)) { @@ -1123,11 +1140,11 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { __block BOOL result = YES; [extensionMap_ - enumerateKeysAndObjectsUsingBlock:^(GPBExtensionField *extension, id obj, + enumerateKeysAndObjectsUsingBlock:^(GPBExtensionDescriptor *extension, + id obj, BOOL *stop) { - GPBExtensionDescriptor *extDesc = extension.descriptor; - if (GPBExtensionIsMessage(extDesc)) { - if (extDesc.isRepeated) { + if (GPBExtensionIsMessage(extension)) { + if (extension.isRepeated) { for (GPBMessage *msg in obj) { if (!msg.initialized) { result = NO; @@ -1259,15 +1276,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%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: +//% case GPBDataType##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]; +//% [output write##TYPE##Array:fieldNumber values:array tag:tag]; //% } else if (fieldType == GPBFieldTypeSingle) { //% [output write##TYPE:fieldNumber -//% TYPE$S value:GPBGet##REAL_TYPE##IvarWithField(self, field)]; +//% TYPE$S value:GPBGetMessage##REAL_TYPE##Field(self, field)]; //% } else { // fieldType == GPBFieldTypeMap //% // Exact type here doesn't matter. //% GPBInt32##ARRAY_TYPE##Dictionary *dict = @@ -1277,10 +1294,10 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //% break; //% //%PDDM-DEFINE FIELD_CASE2(TYPE) -//% case GPBType##TYPE: +//% case GPBDataType##TYPE: //% if (fieldType == GPBFieldTypeRepeated) { //% NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); -//% [output write##TYPE##s:fieldNumber values:array]; +//% [output write##TYPE##Array:fieldNumber values:array]; //% } else if (fieldType == GPBFieldTypeSingle) { //% // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check //% // again. @@ -1289,8 +1306,8 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //% } else { // fieldType == GPBFieldTypeMap //% // Exact type here doesn't matter. //% id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); -//% GPBType mapKeyType = field.mapKeyType; -//% if (mapKeyType == GPBTypeString) { +//% GPBDataType mapKeyDataType = field.mapKeyDataType; +//% if (mapKeyDataType == GPBDataTypeString) { //% GPBDictionaryWriteToStreamInternalHelper(output, dict, field); //% } else { //% [dict writeToCodedOutputStream:output asField:field]; @@ -1299,20 +1316,20 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //% break; //% - switch (GPBGetFieldType(field)) { + switch (GPBGetFieldDataType(field)) { //%PDDM-EXPAND FIELD_CASE(Bool, Bool) // This block of code is generated, do not edit it directly. - case GPBTypeBool: + case GPBDataTypeBool: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBBoolArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeBools:fieldNumber values:array tag:tag]; + [output writeBoolArray:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeBool:fieldNumber - value:GPBGetBoolIvarWithField(self, field)]; + value:GPBGetMessageBoolField(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32BoolDictionary *dict = @@ -1324,15 +1341,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(Fixed32, UInt32) // This block of code is generated, do not edit it directly. - case GPBTypeFixed32: + case GPBDataTypeFixed32: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBUInt32Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeFixed32s:fieldNumber values:array tag:tag]; + [output writeFixed32Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeFixed32:fieldNumber - value:GPBGetUInt32IvarWithField(self, field)]; + value:GPBGetMessageUInt32Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32UInt32Dictionary *dict = @@ -1344,15 +1361,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(SFixed32, Int32) // This block of code is generated, do not edit it directly. - case GPBTypeSFixed32: + case GPBDataTypeSFixed32: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBInt32Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeSFixed32s:fieldNumber values:array tag:tag]; + [output writeSFixed32Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeSFixed32:fieldNumber - value:GPBGetInt32IvarWithField(self, field)]; + value:GPBGetMessageInt32Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32Int32Dictionary *dict = @@ -1364,15 +1381,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(Float, Float) // This block of code is generated, do not edit it directly. - case GPBTypeFloat: + case GPBDataTypeFloat: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBFloatArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeFloats:fieldNumber values:array tag:tag]; + [output writeFloatArray:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeFloat:fieldNumber - value:GPBGetFloatIvarWithField(self, field)]; + value:GPBGetMessageFloatField(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32FloatDictionary *dict = @@ -1384,15 +1401,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(Fixed64, UInt64) // This block of code is generated, do not edit it directly. - case GPBTypeFixed64: + case GPBDataTypeFixed64: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBUInt64Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeFixed64s:fieldNumber values:array tag:tag]; + [output writeFixed64Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeFixed64:fieldNumber - value:GPBGetUInt64IvarWithField(self, field)]; + value:GPBGetMessageUInt64Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32UInt64Dictionary *dict = @@ -1404,15 +1421,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(SFixed64, Int64) // This block of code is generated, do not edit it directly. - case GPBTypeSFixed64: + case GPBDataTypeSFixed64: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBInt64Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeSFixed64s:fieldNumber values:array tag:tag]; + [output writeSFixed64Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeSFixed64:fieldNumber - value:GPBGetInt64IvarWithField(self, field)]; + value:GPBGetMessageInt64Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32Int64Dictionary *dict = @@ -1424,15 +1441,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(Double, Double) // This block of code is generated, do not edit it directly. - case GPBTypeDouble: + case GPBDataTypeDouble: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBDoubleArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeDoubles:fieldNumber values:array tag:tag]; + [output writeDoubleArray:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeDouble:fieldNumber - value:GPBGetDoubleIvarWithField(self, field)]; + value:GPBGetMessageDoubleField(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32DoubleDictionary *dict = @@ -1444,15 +1461,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(Int32, Int32) // This block of code is generated, do not edit it directly. - case GPBTypeInt32: + case GPBDataTypeInt32: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBInt32Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeInt32s:fieldNumber values:array tag:tag]; + [output writeInt32Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeInt32:fieldNumber - value:GPBGetInt32IvarWithField(self, field)]; + value:GPBGetMessageInt32Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32Int32Dictionary *dict = @@ -1464,15 +1481,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(Int64, Int64) // This block of code is generated, do not edit it directly. - case GPBTypeInt64: + case GPBDataTypeInt64: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBInt64Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeInt64s:fieldNumber values:array tag:tag]; + [output writeInt64Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeInt64:fieldNumber - value:GPBGetInt64IvarWithField(self, field)]; + value:GPBGetMessageInt64Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32Int64Dictionary *dict = @@ -1484,15 +1501,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(SInt32, Int32) // This block of code is generated, do not edit it directly. - case GPBTypeSInt32: + case GPBDataTypeSInt32: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBInt32Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeSInt32s:fieldNumber values:array tag:tag]; + [output writeSInt32Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeSInt32:fieldNumber - value:GPBGetInt32IvarWithField(self, field)]; + value:GPBGetMessageInt32Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32Int32Dictionary *dict = @@ -1504,15 +1521,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(SInt64, Int64) // This block of code is generated, do not edit it directly. - case GPBTypeSInt64: + case GPBDataTypeSInt64: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBInt64Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeSInt64s:fieldNumber values:array tag:tag]; + [output writeSInt64Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeSInt64:fieldNumber - value:GPBGetInt64IvarWithField(self, field)]; + value:GPBGetMessageInt64Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32Int64Dictionary *dict = @@ -1524,15 +1541,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(UInt32, UInt32) // This block of code is generated, do not edit it directly. - case GPBTypeUInt32: + case GPBDataTypeUInt32: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBUInt32Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeUInt32s:fieldNumber values:array tag:tag]; + [output writeUInt32Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeUInt32:fieldNumber - value:GPBGetUInt32IvarWithField(self, field)]; + value:GPBGetMessageUInt32Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32UInt32Dictionary *dict = @@ -1544,15 +1561,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(UInt64, UInt64) // This block of code is generated, do not edit it directly. - case GPBTypeUInt64: + case GPBDataTypeUInt64: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBUInt64Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeUInt64s:fieldNumber values:array tag:tag]; + [output writeUInt64Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeUInt64:fieldNumber - value:GPBGetUInt64IvarWithField(self, field)]; + value:GPBGetMessageUInt64Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32UInt64Dictionary *dict = @@ -1564,15 +1581,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE_FULL(Enum, Int32, Enum) // This block of code is generated, do not edit it directly. - case GPBTypeEnum: + case GPBDataTypeEnum: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBEnumArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeEnums:fieldNumber values:array tag:tag]; + [output writeEnumArray:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeEnum:fieldNumber - value:GPBGetInt32IvarWithField(self, field)]; + value:GPBGetMessageInt32Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32EnumDictionary *dict = @@ -1581,23 +1598,23 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } break; -//%PDDM-EXPAND FIELD_CASE2(Data) +//%PDDM-EXPAND FIELD_CASE2(Bytes) // This block of code is generated, do not edit it directly. - case GPBTypeData: + case GPBDataTypeBytes: if (fieldType == GPBFieldTypeRepeated) { NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeDatas:fieldNumber values:array]; + [output writeBytesArray:fieldNumber values:array]; } else if (fieldType == GPBFieldTypeSingle) { // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check // again. - [output writeData:fieldNumber - value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; + [output writeBytes: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) { + GPBDataType mapKeyDataType = field.mapKeyDataType; + if (mapKeyDataType == GPBDataTypeString) { GPBDictionaryWriteToStreamInternalHelper(output, dict, field); } else { [dict writeToCodedOutputStream:output asField:field]; @@ -1608,10 +1625,10 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE2(String) // This block of code is generated, do not edit it directly. - case GPBTypeString: + case GPBDataTypeString: if (fieldType == GPBFieldTypeRepeated) { NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeStrings:fieldNumber values:array]; + [output writeStringArray:fieldNumber values:array]; } else if (fieldType == GPBFieldTypeSingle) { // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check // again. @@ -1620,8 +1637,8 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - GPBType mapKeyType = field.mapKeyType; - if (mapKeyType == GPBTypeString) { + GPBDataType mapKeyDataType = field.mapKeyDataType; + if (mapKeyDataType == GPBDataTypeString) { GPBDictionaryWriteToStreamInternalHelper(output, dict, field); } else { [dict writeToCodedOutputStream:output asField:field]; @@ -1632,10 +1649,10 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE2(Message) // This block of code is generated, do not edit it directly. - case GPBTypeMessage: + case GPBDataTypeMessage: if (fieldType == GPBFieldTypeRepeated) { NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeMessages:fieldNumber values:array]; + [output writeMessageArray:fieldNumber values:array]; } else if (fieldType == GPBFieldTypeSingle) { // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check // again. @@ -1644,8 +1661,8 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - GPBType mapKeyType = field.mapKeyType; - if (mapKeyType == GPBTypeString) { + GPBDataType mapKeyDataType = field.mapKeyDataType; + if (mapKeyDataType == GPBDataTypeString) { GPBDictionaryWriteToStreamInternalHelper(output, dict, field); } else { [dict writeToCodedOutputStream:output asField:field]; @@ -1656,10 +1673,10 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE2(Group) // This block of code is generated, do not edit it directly. - case GPBTypeGroup: + case GPBDataTypeGroup: if (fieldType == GPBFieldTypeRepeated) { NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeGroups:fieldNumber values:array]; + [output writeGroupArray:fieldNumber values:array]; } else if (fieldType == GPBFieldTypeSingle) { // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check // again. @@ -1668,8 +1685,8 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - GPBType mapKeyType = field.mapKeyType; - if (mapKeyType == GPBTypeString) { + GPBDataType mapKeyDataType = field.mapKeyDataType; + if (mapKeyDataType == GPBDataTypeString) { GPBDictionaryWriteToStreamInternalHelper(output, dict, field); } else { [dict writeToCodedOutputStream:output asField:field]; @@ -1683,22 +1700,20 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { #pragma mark - Extensions -- (id)getExtension:(GPBExtensionField *)extension { +- (id)getExtension:(GPBExtensionDescriptor *)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) { + if (extension.isRepeated) { return nil; } // Non messages get their default. - if (!GPBExtensionIsMessage(extDesc)) { - return [extension defaultValue]; + if (!GPBExtensionIsMessage(extension)) { + return extension.defaultValue; } // Check for an autocreated value. @@ -1706,7 +1721,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { value = [autocreatedExtensionMap_ objectForKey:extension]; if (!value) { // Auto create the message extensions to match normal fields. - value = CreateMessageWithAutocreatorForExtension(extDesc.msgClass, self, + value = CreateMessageWithAutocreatorForExtension(extension.msgClass, self, extension); if (autocreatedExtensionMap_ == nil) { @@ -1723,12 +1738,12 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { return value; } -- (id)getExistingExtension:(GPBExtensionField *)extension { +- (id)getExistingExtension:(GPBExtensionDescriptor *)extension { // This is an internal method so we don't need to call CheckExtension(). return [extensionMap_ objectForKey:extension]; } -- (BOOL)hasExtension:(GPBExtensionField *)extension { +- (BOOL)hasExtension:(GPBExtensionDescriptor *)extension { #if DEBUG CheckExtension(self, extension); #endif // DEBUG @@ -1745,11 +1760,11 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { sortedArrayUsingSelector:@selector(compareByFieldNumber:)]; uint32_t start = range.start; uint32_t end = range.end; - for (GPBExtensionField *extension in sortedExtensions) { - uint32_t fieldNumber = [extension fieldNumber]; + for (GPBExtensionDescriptor *extension in sortedExtensions) { + uint32_t fieldNumber = extension.fieldNumber; if (fieldNumber >= start && fieldNumber < end) { id value = [extensionMap_ objectForKey:extension]; - [extension writeValue:value includingTagToCodedOutputStream:output]; + GPBWriteExtensionValueToOutputStream(extension, value, output); } } } @@ -1759,7 +1774,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { sortedArrayUsingSelector:@selector(compareByFieldNumber:)]; } -- (void)setExtension:(GPBExtensionField *)extension value:(id)value { +- (void)setExtension:(GPBExtensionDescriptor *)extension value:(id)value { if (!value) { [self clearExtension:extension]; return; @@ -1767,7 +1782,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { CheckExtension(self, extension); - if ([extension isRepeated]) { + if (extension.repeated) { [NSException raise:NSInvalidArgumentException format:@"Must call addExtension() for repeated types."]; } @@ -1778,7 +1793,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { [extensionMap_ setObject:value forKey:extension]; - GPBExtensionDescriptor *descriptor = extension.descriptor; + GPBExtensionDescriptor *descriptor = extension; if (GPBExtensionIsMessage(descriptor) && !descriptor.isRepeated) { GPBMessage *autocreatedValue = @@ -1793,10 +1808,10 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { GPBBecomeVisibleToAutocreator(self); } -- (void)addExtension:(GPBExtensionField *)extension value:(id)value { +- (void)addExtension:(GPBExtensionDescriptor *)extension value:(id)value { CheckExtension(self, extension); - if (![extension isRepeated]) { + if (!extension.repeated) { [NSException raise:NSInvalidArgumentException format:@"Must call setExtension() for singular types."]; } @@ -1814,12 +1829,12 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { GPBBecomeVisibleToAutocreator(self); } -- (void)setExtension:(GPBExtensionField *)extension +- (void)setExtension:(GPBExtensionDescriptor *)extension index:(NSUInteger)idx value:(id)value { CheckExtension(self, extension); - if (![extension isRepeated]) { + if (!extension.repeated) { [NSException raise:NSInvalidArgumentException format:@"Must call setExtension() for singular types."]; } @@ -1834,7 +1849,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { GPBBecomeVisibleToAutocreator(self); } -- (void)clearExtension:(GPBExtensionField *)extension { +- (void)clearExtension:(GPBExtensionDescriptor *)extension { CheckExtension(self, extension); // Only become visible if there was actually a value to clear. @@ -1862,7 +1877,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { if (GPBCodedInputStreamIsAtEnd(state)) { return; } - NSData *data = GPBCodedInputStreamReadRetainedDataNoCopy(state); + NSData *data = GPBCodedInputStreamReadRetainedBytesNoCopy(state); if (data == nil) { return; } @@ -1903,6 +1918,9 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { @try { [message mergeDelimitedFromCodedInputStream:input extensionRegistry:extensionRegistry]; + if (errorPtr) { + *errorPtr = nil; + } } @catch (NSException *exception) { [message release]; @@ -1942,7 +1960,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { uint32_t typeId = 0; NSData *rawBytes = nil; - GPBExtensionField *extension = nil; + GPBExtensionDescriptor *extension = nil; GPBCodedInputStreamState *state = &input->state_; while (true) { uint32_t tag = GPBCodedInputStreamReadTag(state); @@ -1953,11 +1971,12 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { if (tag == GPBWireFormatMessageSetTypeIdTag) { typeId = GPBCodedInputStreamReadUInt32(state); if (typeId != 0) { - extension = [extensionRegistry getExtension:[self descriptor] - fieldNumber:typeId]; + extension = [extensionRegistry extensionForDescriptor:[self descriptor] + fieldNumber:typeId]; } } else if (tag == GPBWireFormatMessageSetMessageTag) { - rawBytes = [GPBCodedInputStreamReadRetainedDataNoCopy(state) autorelease]; + rawBytes = + [GPBCodedInputStreamReadRetainedBytesNoCopy(state) autorelease]; } else { if (![input skipField:tag]) { break; @@ -1971,9 +1990,11 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { if (extension != nil) { GPBCodedInputStream *newInput = [[GPBCodedInputStream alloc] initWithData:rawBytes]; - [extension mergeFromCodedInputStream:newInput - extensionRegistry:extensionRegistry - message:self]; + GPBExtensionMergeFromInputStream(extension, + extension.packable, + newInput, + extensionRegistry, + self); [newInput release]; } else { GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); @@ -1989,19 +2010,33 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { int32_t fieldNumber = GPBWireFormatGetTagFieldNumber(tag); GPBDescriptor *descriptor = [self descriptor]; - GPBExtensionField *extension = - [extensionRegistry getExtension:descriptor fieldNumber:fieldNumber]; - + GPBExtensionDescriptor *extension = + [extensionRegistry extensionForDescriptor: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]; + if (extension.wireType == wireType) { + GPBExtensionMergeFromInputStream(extension, + extension.packable, + input, + extensionRegistry, + self); + return YES; + } + // Primitive, repeated types can be packed on unpacked on the wire, and are + // parsed either way. + if ([extension isRepeated] && + !GPBDataTypeIsObject(extension->description_->dataType) && + (extension.alternateWireType == wireType)) { + GPBExtensionMergeFromInputStream(extension, + !extension.packable, + input, + extensionRegistry, + self); return YES; } } @@ -2020,1052 +2055,311 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { #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]; +static void MergeSingleFieldFromCodedInputStream( + GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, + GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) { + GPBDataType fieldDataType = GPBGetFieldDataType(field); + switch (fieldDataType) { +#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE) \ + case GPBDataType##NAME: { \ + TYPE val = GPBCodedInputStreamRead##NAME(&input->state_); \ + GPBSet##FUNC_TYPE##IvarWithFieldInternal(self, field, val, syntax); \ + break; \ + } +#define CASE_SINGLE_OBJECT(NAME) \ + case GPBDataType##NAME: { \ + id val = GPBCodedInputStreamReadRetained##NAME(&input->state_); \ + GPBSetRetainedObjectIvarWithFieldInternal(self, field, val, syntax); \ + break; \ + } + CASE_SINGLE_POD(Bool, BOOL, Bool) + CASE_SINGLE_POD(Fixed32, uint32_t, UInt32) + CASE_SINGLE_POD(SFixed32, int32_t, Int32) + CASE_SINGLE_POD(Float, float, Float) + CASE_SINGLE_POD(Fixed64, uint64_t, UInt64) + CASE_SINGLE_POD(SFixed64, int64_t, Int64) + CASE_SINGLE_POD(Double, double, Double) + CASE_SINGLE_POD(Int32, int32_t, Int32) + CASE_SINGLE_POD(Int64, int64_t, Int64) + CASE_SINGLE_POD(SInt32, int32_t, Int32) + CASE_SINGLE_POD(SInt64, int64_t, Int64) + CASE_SINGLE_POD(UInt32, uint32_t, UInt32) + CASE_SINGLE_POD(UInt64, uint64_t, UInt64) + CASE_SINGLE_OBJECT(Bytes) + CASE_SINGLE_OBJECT(String) +#undef CASE_SINGLE_POD +#undef CASE_SINGLE_OBJECT + + case GPBDataTypeMessage: { + if (GPBGetHasIvarField(self, field)) { + // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has + // check again. + GPBMessage *message = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [input readMessage:message extensionRegistry:extensionRegistry]; } 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]; + GPBMessage *message = [[field.msgClass alloc] init]; + [input readMessage:message extensionRegistry:extensionRegistry]; + GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax); } - GPBCodedInputStreamPopLimit(state, limit); - } else { - uint32_t val = GPBCodedInputStreamReadFixed32(state); - [array addValue:val]; + break; } - } 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]; + case GPBDataTypeGroup: { + if (GPBGetHasIvarField(self, field)) { + // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has + // check again. + GPBMessage *message = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [input readGroup:GPBFieldNumber(field) + message:message + extensionRegistry:extensionRegistry]; + } else { + GPBMessage *message = [[field.msgClass alloc] init]; + [input readGroup:GPBFieldNumber(field) + message:message + extensionRegistry:extensionRegistry]; + GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax); } - GPBCodedInputStreamPopLimit(state, limit); - } else { - int64_t val = GPBCodedInputStreamReadInt64(state); - [array addValue:val]; + break; } - } 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]; + case GPBDataTypeEnum: { + int32_t val = GPBCodedInputStreamReadEnum(&input->state_); + if (GPBHasPreservingUnknownEnumSemantics(syntax) || + [field isValidEnumValue:val]) { + GPBSetInt32IvarWithFieldInternal(self, field, val, syntax); + } else { + GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); + [unknownFields mergeVarintField:GPBFieldNumber(field) value: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; + } // switch } -//%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 void MergeRepeatedPackedFieldFromCodedInputStream( + GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, + GPBCodedInputStream *input) { + GPBDataType fieldDataType = GPBGetFieldDataType(field); + GPBCodedInputStreamState *state = &input->state_; + id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax); + int32_t length = GPBCodedInputStreamReadInt32(state); + size_t limit = GPBCodedInputStreamPushLimit(state, length); + while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { + switch (fieldDataType) { +#define CASE_REPEATED_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \ + case GPBDataType##NAME: { \ + TYPE val = GPBCodedInputStreamRead##NAME(state); \ + [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \ + break; \ + } + CASE_REPEATED_PACKED_POD(Bool, BOOL, Bool) + CASE_REPEATED_PACKED_POD(Fixed32, uint32_t, UInt32) + CASE_REPEATED_PACKED_POD(SFixed32, int32_t, Int32) + CASE_REPEATED_PACKED_POD(Float, float, Float) + CASE_REPEATED_PACKED_POD(Fixed64, uint64_t, UInt64) + CASE_REPEATED_PACKED_POD(SFixed64, int64_t, Int64) + CASE_REPEATED_PACKED_POD(Double, double, Double) + CASE_REPEATED_PACKED_POD(Int32, int32_t, Int32) + CASE_REPEATED_PACKED_POD(Int64, int64_t, Int64) + CASE_REPEATED_PACKED_POD(SInt32, int32_t, Int32) + CASE_REPEATED_PACKED_POD(SInt64, int64_t, Int64) + CASE_REPEATED_PACKED_POD(UInt32, uint32_t, UInt32) + CASE_REPEATED_PACKED_POD(UInt64, uint64_t, UInt64) +#undef CASE_REPEATED_PACKED_POD + + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: + NSCAssert(NO, @"Non primitive types can't be packed"); + break; -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]; + case GPBDataTypeEnum: { + int32_t val = GPBCodedInputStreamReadEnum(state); + if (GPBHasPreservingUnknownEnumSemantics(syntax) || + [field isValidEnumValue:val]) { + [(GPBEnumArray*)genericArray addRawValue:val]; + } else { + GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); + [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; + } + break; } - 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; + } // switch + } // while(BytesUntilLimit() > 0) + GPBCodedInputStreamPopLimit(state, limit); } -//%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]; +static void MergeRepeatedNotPackedFieldFromCodedInputStream( + GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, + GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) { + GPBCodedInputStreamState *state = &input->state_; + id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax); + switch (GPBGetFieldDataType(field)) { +#define CASE_REPEATED_NOT_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \ + case GPBDataType##NAME: { \ + TYPE val = GPBCodedInputStreamRead##NAME(state); \ + [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \ + break; \ + } +#define CASE_REPEATED_NOT_PACKED_OBJECT(NAME) \ + case GPBDataType##NAME: { \ + id val = GPBCodedInputStreamReadRetained##NAME(state); \ + [(NSMutableArray*)genericArray addObject:val]; \ + [val release]; \ + break; \ + } + CASE_REPEATED_NOT_PACKED_POD(Bool, BOOL, Bool) + CASE_REPEATED_NOT_PACKED_POD(Fixed32, uint32_t, UInt32) + CASE_REPEATED_NOT_PACKED_POD(SFixed32, int32_t, Int32) + CASE_REPEATED_NOT_PACKED_POD(Float, float, Float) + CASE_REPEATED_NOT_PACKED_POD(Fixed64, uint64_t, UInt64) + CASE_REPEATED_NOT_PACKED_POD(SFixed64, int64_t, Int64) + CASE_REPEATED_NOT_PACKED_POD(Double, double, Double) + CASE_REPEATED_NOT_PACKED_POD(Int32, int32_t, Int32) + CASE_REPEATED_NOT_PACKED_POD(Int64, int64_t, Int64) + CASE_REPEATED_NOT_PACKED_POD(SInt32, int32_t, Int32) + CASE_REPEATED_NOT_PACKED_POD(SInt64, int64_t, Int64) + CASE_REPEATED_NOT_PACKED_POD(UInt32, uint32_t, UInt32) + CASE_REPEATED_NOT_PACKED_POD(UInt64, uint64_t, UInt64) + CASE_REPEATED_NOT_PACKED_OBJECT(Bytes) + CASE_REPEATED_NOT_PACKED_OBJECT(String) +#undef CASE_REPEATED_NOT_PACKED_POD +#undef CASE_NOT_PACKED_OBJECT + case GPBDataTypeMessage: { + GPBMessage *message = [[field.msgClass alloc] init]; + [input readMessage:message extensionRegistry:extensionRegistry]; + [(NSMutableArray*)genericArray addObject:message]; + [message release]; + break; } - } 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]; + case GPBDataTypeGroup: { + GPBMessage *message = [[field.msgClass alloc] init]; + [input readGroup:GPBFieldNumber(field) + message:message + extensionRegistry:extensionRegistry]; + [(NSMutableArray*)genericArray addObject:message]; + [message release]; + break; } - } 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]; + case GPBDataTypeEnum: { + int32_t val = GPBCodedInputStreamReadEnum(state); + if (GPBHasPreservingUnknownEnumSemantics(syntax) || + [field isValidEnumValue:val]) { + [(GPBEnumArray*)genericArray addRawValue:val]; + } else { + GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); + [unknownFields mergeVarintField:GPBFieldNumber(field) value: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); + break; } - } - return NO; + } // switch } -//%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); + GPBCodedInputStreamState *state = &input->state_; + uint32_t tag = 0; NSUInteger startingIndex = 0; NSArray *fields = descriptor->fields_; - NSUInteger count = fields.count; + NSUInteger numFields = fields.count; while (YES) { BOOL merged = NO; - context.tag = GPBCodedInputStreamReadTag(&input->state_); - for (NSUInteger i = 0; i < count; ++i) { - if (startingIndex >= count) startingIndex = 0; + tag = GPBCodedInputStreamReadTag(state); + for (NSUInteger i = 0; i < numFields; ++i) { + if (startingIndex >= numFields) startingIndex = 0; GPBFieldDescriptor *fieldDescriptor = fields[startingIndex]; - if (GPBFieldTag(fieldDescriptor) == context.tag) { - GPBApplyFunction function = funcs[GPBGetFieldType(fieldDescriptor)]; - function(fieldDescriptor, &context); + if (GPBFieldTag(fieldDescriptor) == tag) { + GPBFieldType fieldType = fieldDescriptor.fieldType; + if (fieldType == GPBFieldTypeSingle) { + MergeSingleFieldFromCodedInputStream(self, fieldDescriptor, syntax, + input, extensionRegistry); + // Well formed protos will only have a single field once, advance + // the starting index to the next field. + startingIndex += 1; + } else if (fieldType == GPBFieldTypeRepeated) { + if (fieldDescriptor.isPackable) { + MergeRepeatedPackedFieldFromCodedInputStream( + self, fieldDescriptor, syntax, input); + // Well formed protos will only have a repeated field that is + // packed once, advance the starting index to the next field. + startingIndex += 1; + } else { + MergeRepeatedNotPackedFieldFromCodedInputStream( + self, fieldDescriptor, syntax, input, extensionRegistry); + } + } else { // fieldType == GPBFieldTypeMap + // GPB*Dictionary or NSDictionary, exact type doesn't matter at this + // point. + id map = GetOrCreateMapIvarWithField(self, fieldDescriptor, syntax); + [input readMapEntry:map + extensionRegistry:extensionRegistry + field:fieldDescriptor + parentMessage:self]; + } merged = YES; break; } else { startingIndex += 1; } + } // for(i < numFields) + + if (!merged) { + // Primitive, repeated types can be packed on unpacked on the wire, and + // are parsed either way. The above loop covered tag in the preferred + // for, so this need to check the alternate form. + for (NSUInteger i = 0; i < numFields; ++i) { + if (startingIndex >= numFields) startingIndex = 0; + GPBFieldDescriptor *fieldDescriptor = fields[startingIndex]; + if ((fieldDescriptor.fieldType == GPBFieldTypeRepeated) && + !GPBFieldDataTypeIsObject(fieldDescriptor) && + (GPBFieldAlternateTag(fieldDescriptor) == tag)) { + BOOL alternateIsPacked = !fieldDescriptor.isPackable; + if (alternateIsPacked) { + MergeRepeatedPackedFieldFromCodedInputStream( + self, fieldDescriptor, syntax, input); + // Well formed protos will only have a repeated field that is + // packed once, advance the starting index to the next field. + startingIndex += 1; + } else { + MergeRepeatedNotPackedFieldFromCodedInputStream( + self, fieldDescriptor, syntax, input, extensionRegistry); + } + merged = YES; + break; + } else { + startingIndex += 1; + } + } } + if (!merged) { - if (context.tag == 0) { + if (tag == 0) { // zero signals EOF / limit reached return; } else { if (GPBPreserveUnknownFields(syntax)) { if (![self parseUnknownField:input extensionRegistry:extensionRegistry - tag:context.tag]) { + tag:tag]) { // it's an endgroup tag return; } } else { - if (![input skipField:context.tag]) { + if (![input skipField: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. + } // if(!merged) -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; + } // while(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; -} +#pragma mark - MergeFrom Support - (void)mergeFrom:(GPBMessage *)other { Class selfClass = [self class]; @@ -3076,21 +2370,140 @@ static BOOL MergeFromObject(GPBFieldDescriptor *field, void *voidContext) { 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. + // We assume something will be done and become visible. GPBBecomeVisibleToAutocreator(self); + GPBDescriptor *descriptor = [[self class] descriptor]; + GPBFileSyntax syntax = descriptor.file.syntax; + + for (GPBFieldDescriptor *field in descriptor->fields_) { + GPBFieldType fieldType = field.fieldType; + if (fieldType == GPBFieldTypeSingle) { + int32_t hasIndex = GPBFieldHasIndex(field); + uint32_t fieldNumber = GPBFieldNumber(field); + if (!GPBGetHasIvar(other, hasIndex, fieldNumber)) { + // Other doesn't have the field set, on to the next. + continue; + } + GPBDataType fieldDataType = GPBGetFieldDataType(field); + switch (fieldDataType) { + case GPBDataTypeBool: + GPBSetBoolIvarWithFieldInternal( + self, field, GPBGetMessageBoolField(other, field), syntax); + break; + case GPBDataTypeSFixed32: + case GPBDataTypeEnum: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + GPBSetInt32IvarWithFieldInternal( + self, field, GPBGetMessageInt32Field(other, field), syntax); + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + GPBSetUInt32IvarWithFieldInternal( + self, field, GPBGetMessageUInt32Field(other, field), syntax); + break; + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + GPBSetInt64IvarWithFieldInternal( + self, field, GPBGetMessageInt64Field(other, field), syntax); + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + GPBSetUInt64IvarWithFieldInternal( + self, field, GPBGetMessageUInt64Field(other, field), syntax); + break; + case GPBDataTypeFloat: + GPBSetFloatIvarWithFieldInternal( + self, field, GPBGetMessageFloatField(other, field), syntax); + break; + case GPBDataTypeDouble: + GPBSetDoubleIvarWithFieldInternal( + self, field, GPBGetMessageDoubleField(other, field), syntax); + break; + case GPBDataTypeBytes: + case GPBDataTypeString: { + id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field); + GPBSetObjectIvarWithFieldInternal(self, field, otherVal, syntax); + break; + } + case GPBDataTypeMessage: + case GPBDataTypeGroup: { + id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field); + if (GPBGetHasIvar(self, hasIndex, fieldNumber)) { + GPBMessage *message = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [message mergeFrom:otherVal]; + } else { + GPBMessage *message = [otherVal copy]; + GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, + syntax); + } + break; + } + } // switch() + } else 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(other, field); + if (otherArray) { + GPBDataType fieldDataType = field->description_->dataType; + if (GPBDataTypeIsObject(fieldDataType)) { + NSMutableArray *resultArray = + GetOrCreateArrayIvarWithField(self, field, syntax); + [resultArray addObjectsFromArray:otherArray]; + } else if (fieldDataType == GPBDataTypeEnum) { + GPBEnumArray *resultArray = + GetOrCreateArrayIvarWithField(self, field, syntax); + [resultArray addRawValuesFromArray:otherArray]; + } else { + // The array type doesn't matter, that all implment + // -addValuesFromArray:. + GPBInt32Array *resultArray = + GetOrCreateArrayIvarWithField(self, field, syntax); + [resultArray addValuesFromArray:otherArray]; + } + } + } else { // 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(other, field); + if (otherDict) { + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = field->description_->dataType; + if (GPBDataTypeIsObject(keyDataType) && + GPBDataTypeIsObject(valueDataType)) { + NSMutableDictionary *resultDict = + GetOrCreateMapIvarWithField(self, field, syntax); + [resultDict addEntriesFromDictionary:otherDict]; + } else if (valueDataType == GPBDataTypeEnum) { + // The exact type doesn't matter, just need to know it is a + // GPB*EnumDictionary. + GPBInt32EnumDictionary *resultDict = + GetOrCreateMapIvarWithField(self, field, syntax); + [resultDict addRawEntriesFromDictionary:otherDict]; + } else { + // The exact type doesn't matter, they all implement + // -addEntriesFromDictionary:. + GPBInt32Int32Dictionary *resultDict = + GetOrCreateMapIvarWithField(self, field, syntax); + [resultDict addEntriesFromDictionary:otherDict]; + } + } + } // if (fieldType)..else if...else + } // for(fields) + // Unknown fields. if (!unknownFields_) { - [self setUnknownFields:context.other.unknownFields]; + [self setUnknownFields:other.unknownFields]; } else { - [unknownFields_ mergeUnknownFields:context.other.unknownFields]; + [unknownFields_ mergeUnknownFields:other.unknownFields]; } + // Extensions + if (other->extensionMap_.count == 0) { return; } @@ -3099,17 +2512,16 @@ static BOOL MergeFromObject(GPBFieldDescriptor *field, void *voidContext) { 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); + for (GPBExtensionDescriptor *extension in other->extensionMap_) { + id otherValue = [other->extensionMap_ objectForKey:extension]; + id value = [extensionMap_ objectForKey:extension]; + BOOL isMessageExtension = GPBExtensionIsMessage(extension); - if ([thisField isRepeated]) { + if (extension.repeated) { NSMutableArray *list = value; if (list == nil) { list = [[NSMutableArray alloc] init]; - [extensionMap_ setObject:list forKey:thisField]; + [extensionMap_ setObject:list forKey:extension]; [list release]; } if (isMessageExtension) { @@ -3127,20 +2539,20 @@ static BOOL MergeFromObject(GPBFieldDescriptor *field, void *voidContext) { [(GPBMessage *)value mergeFrom:(GPBMessage *)otherValue]; } else { GPBMessage *copiedValue = [otherValue copy]; - [extensionMap_ setObject:copiedValue forKey:thisField]; + [extensionMap_ setObject:copiedValue forKey:extension]; [copiedValue release]; } } else { - [extensionMap_ setObject:otherValue forKey:thisField]; + [extensionMap_ setObject:otherValue forKey:extension]; } } - if (isMessageExtension && !thisFieldDescriptor.isRepeated) { + if (isMessageExtension && !extension.isRepeated) { GPBMessage *autocreatedValue = - [[autocreatedExtensionMap_ objectForKey:thisField] retain]; + [[autocreatedExtensionMap_ objectForKey:extension] retain]; // Must remove from the map before calling GPBClearMessageAutocreator() // so that GPBClearMessageAutocreator() knows its safe to clear. - [autocreatedExtensionMap_ removeObjectForKey:thisField]; + [autocreatedExtensionMap_ removeObjectForKey:extension]; GPBClearMessageAutocreator(autocreatedValue); [autocreatedValue release]; } @@ -3148,259 +2560,7 @@ static BOOL MergeFromObject(GPBFieldDescriptor *field, void *voidContext) { } } -#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; -} +#pragma mark - isEqual: & hash Support - (BOOL)isEqual:(GPBMessage *)other { if (other == self) { @@ -3410,12 +2570,97 @@ static BOOL IsEqualObject(GPBFieldDescriptor *field, void *voidContext) { ![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; - } + + GPBDescriptor *descriptor = [[self class] descriptor]; + uint8_t *selfStorage = (uint8_t *)messageStorage_; + uint8_t *otherStorage = (uint8_t *)other->messageStorage_; + + for (GPBFieldDescriptor *field in descriptor->fields_) { + if (GPBFieldIsMapOrArray(field)) { + // In the case of a list or map, there is no _hasIvar to worry about. + // NOTE: These are NSArray/GPB*Array or NSDictionary/GPB*Dictionary, but + // the type doesn't really matter as the objects all support -count and + // -isEqual:. + NSArray *resultMapOrArray = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + NSArray *otherMapOrArray = + GPBGetObjectIvarWithFieldNoAutocreate(other, field); + // nil and empty are equal + if (resultMapOrArray.count != 0 || otherMapOrArray.count != 0) { + if (![resultMapOrArray isEqual:otherMapOrArray]) { + return NO; + } + } + } else { // Single field + int32_t hasIndex = GPBFieldHasIndex(field); + uint32_t fieldNum = GPBFieldNumber(field); + BOOL selfHas = GPBGetHasIvar(self, hasIndex, fieldNum); + BOOL otherHas = GPBGetHasIvar(other, hasIndex, fieldNum); + if (selfHas != otherHas) { + return NO; // Differing has values, not equal. + } + if (!selfHas) { + // Same has values, was no, nothing else to check for this field. + continue; + } + // Now compare the values. + GPBDataType fieldDataType = GPBGetFieldDataType(field); + size_t fieldOffset = field->description_->offset; + switch (fieldDataType) { + case GPBDataTypeBool: { + BOOL *selfValPtr = (BOOL *)&selfStorage[fieldOffset]; + BOOL *otherValPtr = (BOOL *)&otherStorage[fieldOffset]; + if (*selfValPtr != *otherValPtr) { + return NO; + } + break; + } + case GPBDataTypeSFixed32: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + case GPBDataTypeEnum: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + case GPBDataTypeFloat: { + _GPBCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits); + // These are all 32bit, signed/unsigned doesn't matter for equality. + uint32_t *selfValPtr = (uint32_t *)&selfStorage[fieldOffset]; + uint32_t *otherValPtr = (uint32_t *)&otherStorage[fieldOffset]; + if (*selfValPtr != *otherValPtr) { + return NO; + } + break; + } + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + case GPBDataTypeDouble: { + _GPBCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits); + // These are all 64bit, signed/unsigned doesn't matter for equality. + uint64_t *selfValPtr = (uint64_t *)&selfStorage[fieldOffset]; + uint64_t *otherValPtr = (uint64_t *)&otherStorage[fieldOffset]; + if (*selfValPtr != *otherValPtr) { + return NO; + } + break; + } + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: { + // Type doesn't matter here, they all implement -isEqual:. + id *selfValPtr = (id *)&selfStorage[fieldOffset]; + id *otherValPtr = (id *)&otherStorage[fieldOffset]; + if (![*selfValPtr isEqual:*otherValPtr]) { + return NO; + } + break; + } + } // switch() + } // if(mapOrArray)...else + } // for(fields) // nil and empty are equal if (extensionMap_.count != 0 || other->extensionMap_.count != 0) { @@ -3425,13 +2670,14 @@ static BOOL IsEqualObject(GPBFieldDescriptor *field, void *voidContext) { } // nil and empty are equal - GPBUnknownFieldSet *otherUnknowns = other.unknownFields; + GPBUnknownFieldSet *otherUnknowns = other->unknownFields_; if ([unknownFields_ countOfFields] != 0 || [otherUnknowns countOfFields] != 0) { if (![unknownFields_ isEqual:otherUnknowns]) { return NO; } } + return YES; } @@ -3449,22 +2695,88 @@ static BOOL IsEqualObject(GPBFieldDescriptor *field, void *voidContext) { - (NSUInteger)hash { GPBDescriptor *descriptor = [[self class] descriptor]; const NSUInteger prime = 19; + uint8_t *storage = (uint8_t *)messageStorage_; - // 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. + // Start with the descriptor and then mix it with some instance info. + // 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) { + NSUInteger count = mapOrArray.count; + if (count) { + // NSArray/NSDictionary use count, use the field number and the count. result = prime * result + GPBFieldNumber(field); + result = prime * result + count; } } else if (GPBGetHasIvarField(self, field)) { - result = prime * result + GPBFieldNumber(field); + // Just using the field number seemed simple/fast, but then a small + // message class where all the same fields are always set (to different + // things would end up all with the same hash, so pull in some data). + GPBDataType fieldDataType = GPBGetFieldDataType(field); + size_t fieldOffset = field->description_->offset; + switch (fieldDataType) { + case GPBDataTypeBool: { + BOOL *valPtr = (BOOL *)&storage[fieldOffset]; + result = prime * result + *valPtr; + break; + } + case GPBDataTypeSFixed32: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + case GPBDataTypeEnum: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + case GPBDataTypeFloat: { + _GPBCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits); + // These are all 32bit, just mix it in. + uint32_t *valPtr = (uint32_t *)&storage[fieldOffset]; + result = prime * result + *valPtr; + break; + } + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + case GPBDataTypeDouble: { + _GPBCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits); + // These are all 64bit, just mix what fits into an NSUInteger in. + uint64_t *valPtr = (uint64_t *)&storage[fieldOffset]; + result = prime * result + (NSUInteger)(*valPtr); + break; + } + case GPBDataTypeBytes: + case GPBDataTypeString: { + // Type doesn't matter here, they both implement -hash:. + id *valPtr = (id *)&storage[fieldOffset]; + result = prime * result + [*valPtr hash]; + break; + } + + case GPBDataTypeMessage: + case GPBDataTypeGroup: { + GPBMessage **valPtr = (GPBMessage **)&storage[fieldOffset]; + // Could call -hash on the sub message, but that could recurse pretty + // deep; follow the lead of NSArray/NSDictionary and don't really + // recurse for hash, instead use the field number and the descriptor + // of the sub message. Yes, this could suck for a bunch of messages + // where they all only differ in the sub messages, but if you are + // using a message with sub messages for something that needs -hash, + // odds are you are also copying them as keys, and that deep copy + // will also suck. + result = prime * result + GPBFieldNumber(field); + result = prime * result + (NSUInteger)[[*valPtr class] descriptor]; + break; + } + } // switch() } } + + // Unknowns and extensions are not included. + return result; } @@ -3487,1325 +2799,245 @@ static BOOL IsEqualObject(GPBFieldDescriptor *field, void *voidContext) { #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. +#pragma mark - SerializedSize -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. +- (size_t)serializedSize { + GPBDescriptor *descriptor = [[self class] descriptor]; + size_t result = 0; -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; -} + // Has check is done explicitly, so GPBGetObjectIvarWithFieldNoAutocreate() + // avoids doing the has check again. -//%PDDM-EXPAND SERIALIZED_SIZE_OBJECT_FUNC(Message) -// This block of code is generated, do not edit it directly. + // Fields. + for (GPBFieldDescriptor *fieldDescriptor in descriptor->fields_) { + GPBFieldType fieldType = fieldDescriptor.fieldType; + GPBDataType fieldDataType = GPBGetFieldDataType(fieldDescriptor); -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; -} + // Single Fields + if (fieldType == GPBFieldTypeSingle) { + BOOL selfHas = GPBGetHasIvarField(self, fieldDescriptor); + if (!selfHas) { + continue; // Nothing to do. + } -//%PDDM-EXPAND SERIALIZED_SIZE_OBJECT_FUNC(Group) -// This block of code is generated, do not edit it directly. + uint32_t fieldNumber = GPBFieldNumber(fieldDescriptor); -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]; + switch (fieldDataType) { +#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE) \ + case GPBDataType##NAME: { \ + TYPE fieldVal = GPBGetMessage##FUNC_TYPE##Field(self, fieldDescriptor); \ + result += GPBCompute##NAME##Size(fieldNumber, fieldVal); \ + break; \ + } +#define CASE_SINGLE_OBJECT(NAME) \ + case GPBDataType##NAME: { \ + id fieldVal = GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); \ + result += GPBCompute##NAME##Size(fieldNumber, fieldVal); \ + break; \ + } + CASE_SINGLE_POD(Bool, BOOL, Bool) + CASE_SINGLE_POD(Fixed32, uint32_t, UInt32) + CASE_SINGLE_POD(SFixed32, int32_t, Int32) + CASE_SINGLE_POD(Float, float, Float) + CASE_SINGLE_POD(Fixed64, uint64_t, UInt64) + CASE_SINGLE_POD(SFixed64, int64_t, Int64) + CASE_SINGLE_POD(Double, double, Double) + CASE_SINGLE_POD(Int32, int32_t, Int32) + CASE_SINGLE_POD(Int64, int64_t, Int64) + CASE_SINGLE_POD(SInt32, int32_t, Int32) + CASE_SINGLE_POD(SInt64, int64_t, Int64) + CASE_SINGLE_POD(UInt32, uint32_t, UInt32) + CASE_SINGLE_POD(UInt64, uint64_t, UInt64) + CASE_SINGLE_OBJECT(Bytes) + CASE_SINGLE_OBJECT(String) + CASE_SINGLE_OBJECT(Message) + CASE_SINGLE_OBJECT(Group) + CASE_SINGLE_POD(Enum, int32_t, Int32) +#undef CASE_SINGLE_POD +#undef CASE_SINGLE_OBJECT + } + + // Repeated Fields + } else if (fieldType == GPBFieldTypeRepeated) { + id genericArray = + GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); + NSUInteger count = [genericArray count]; + if (count == 0) { + continue; // Nothing to add. + } + __block size_t dataSize = 0; + + switch (fieldDataType) { +#define CASE_REPEATED_POD(NAME, TYPE, ARRAY_TYPE) \ + CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ) +#define CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ARRAY_ACCESSOR_NAME) \ + case GPBDataType##NAME: { \ + GPB##ARRAY_TYPE##Array *array = genericArray; \ + [array enumerate##ARRAY_ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) { \ + _Pragma("unused(idx, stop)"); \ + dataSize += GPBCompute##NAME##SizeNoTag(value); \ + }]; \ + break; \ + } +#define CASE_REPEATED_OBJECT(NAME) \ + case GPBDataType##NAME: { \ + for (id value in genericArray) { \ + dataSize += GPBCompute##NAME##SizeNoTag(value); \ + } \ + break; \ + } + CASE_REPEATED_POD(Bool, BOOL, Bool) + CASE_REPEATED_POD(Fixed32, uint32_t, UInt32) + CASE_REPEATED_POD(SFixed32, int32_t, Int32) + CASE_REPEATED_POD(Float, float, Float) + CASE_REPEATED_POD(Fixed64, uint64_t, UInt64) + CASE_REPEATED_POD(SFixed64, int64_t, Int64) + CASE_REPEATED_POD(Double, double, Double) + CASE_REPEATED_POD(Int32, int32_t, Int32) + CASE_REPEATED_POD(Int64, int64_t, Int64) + CASE_REPEATED_POD(SInt32, int32_t, Int32) + CASE_REPEATED_POD(SInt64, int64_t, Int64) + CASE_REPEATED_POD(UInt32, uint32_t, UInt32) + CASE_REPEATED_POD(UInt64, uint64_t, UInt64) + CASE_REPEATED_OBJECT(Bytes) + CASE_REPEATED_OBJECT(String) + CASE_REPEATED_OBJECT(Message) + CASE_REPEATED_OBJECT(Group) + CASE_REPEATED_POD_EXTRA(Enum, int32_t, Enum, Raw) +#undef CASE_REPEATED_POD +#undef CASE_REPEATED_POD_EXTRA +#undef CASE_REPEATED_OBJECT + } // switch + result += dataSize; + size_t tagSize = GPBComputeTagSize(GPBFieldNumber(fieldDescriptor)); + if (fieldDataType == GPBDataTypeGroup) { + // Groups have both a start and an end tag. + tagSize *= 2; + } + if (fieldDescriptor.isPackable) { + result += tagSize; + result += GPBComputeSizeTSizeAsInt32NoTag(dataSize); + } else { + result += count * tagSize; + } + + // Map<> Fields + } else { // fieldType == GPBFieldTypeMap + if (GPBDataTypeIsObject(fieldDataType) && + (fieldDescriptor.mapKeyDataType == GPBDataTypeString)) { + // If key type was string, then the map is an NSDictionary. + NSDictionary *map = + GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); + if (map) { + result += GPBDictionaryComputeSizeInternalHelper(map, fieldDescriptor); + } + } else { + // Type will be GPB*GroupDictionary, exact type doesn't matter. + GPBInt32Int32Dictionary *map = + GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); + result += [map computeSerializedSizeAsField:fieldDescriptor]; + } } - } - return YES; -} + } // for(fields) -//%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]; + result += [unknownFields_ serializedSizeAsMessageSet]; } else { - context.outSize += [unknownFields_ serializedSize]; + result += [unknownFields_ serializedSize]; } + // Add any extensions. - for (GPBExtensionField *extension in extensionMap_) { + for (GPBExtensionDescriptor *extension in extensionMap_) { id value = [extensionMap_ objectForKey:extension]; - context.outSize += [extension computeSerializedSizeIncludingTag:value]; + result += GPBComputeExtensionSerializedSizeIncludingTag(extension, value); } - return context.outSize; + return result; } #pragma mark - Resolve Methods Support -typedef struct IvarAccessorMethodContext { - GPBFileSyntax syntax; +typedef struct ResolveIvarAccessorMethodResult { 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; -} +} ResolveIvarAccessorMethodResult; -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; +static void ResolveIvarGet(GPBFieldDescriptor *field, + ResolveIvarAccessorMethodResult *result) { + GPBDataType fieldDataType = GPBGetFieldDataType(field); + switch (fieldDataType) { +#define CASE_GET(NAME, TYPE, TRUE_NAME) \ + case GPBDataType##NAME: { \ + result->impToAdd = imp_implementationWithBlock(^(id obj) { \ + return GPBGetMessage##TRUE_NAME##Field(obj, field); \ + }); \ + result->encodingSelector = @selector(get##NAME); \ + break; \ + } +#define CASE_GET_OBJECT(NAME, TYPE, TRUE_NAME) \ + case GPBDataType##NAME: { \ + result->impToAdd = imp_implementationWithBlock(^(id obj) { \ + return GPBGetObjectIvarWithField(obj, field); \ + }); \ + result->encodingSelector = @selector(get##NAME); \ + break; \ + } + CASE_GET(Bool, BOOL, Bool) + CASE_GET(Fixed32, uint32_t, UInt32) + CASE_GET(SFixed32, int32_t, Int32) + CASE_GET(Float, float, Float) + CASE_GET(Fixed64, uint64_t, UInt64) + CASE_GET(SFixed64, int64_t, Int64) + CASE_GET(Double, double, Double) + CASE_GET(Int32, int32_t, Int32) + CASE_GET(Int64, int64_t, Int64) + CASE_GET(SInt32, int32_t, Int32) + CASE_GET(SInt64, int64_t, Int64) + CASE_GET(UInt32, uint32_t, UInt32) + CASE_GET(UInt64, uint64_t, UInt64) + CASE_GET_OBJECT(Bytes, id, Object) + CASE_GET_OBJECT(String, id, Object) + CASE_GET_OBJECT(Message, id, Object) + CASE_GET_OBJECT(Group, id, Object) + CASE_GET(Enum, int32_t, Enum) +#undef CASE_GET + } +} + +static void ResolveIvarSet(GPBFieldDescriptor *field, + GPBFileSyntax syntax, + ResolveIvarAccessorMethodResult *result) { + GPBDataType fieldDataType = GPBGetFieldDataType(field); + switch (fieldDataType) { +#define CASE_SET(NAME, TYPE, TRUE_NAME) \ + case GPBDataType##NAME: { \ + result->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) { \ + return GPBSet##TRUE_NAME##IvarWithFieldInternal(obj, field, value, syntax); \ + }); \ + result->encodingSelector = @selector(set##NAME:); \ + break; \ + } + CASE_SET(Bool, BOOL, Bool) + CASE_SET(Fixed32, uint32_t, UInt32) + CASE_SET(SFixed32, int32_t, Int32) + CASE_SET(Float, float, Float) + CASE_SET(Fixed64, uint64_t, UInt64) + CASE_SET(SFixed64, int64_t, Int64) + CASE_SET(Double, double, Double) + CASE_SET(Int32, int32_t, Int32) + CASE_SET(Int64, int64_t, Int64) + CASE_SET(SInt32, int32_t, Int32) + CASE_SET(SInt64, int64_t, Int64) + CASE_SET(UInt32, uint32_t, UInt32) + CASE_SET(UInt64, uint64_t, UInt64) + CASE_SET(Bytes, id, Object) + CASE_SET(String, id, Object) + CASE_SET(Message, id, Object) + CASE_SET(Group, id, Object) + CASE_SET(Enum, int32_t, Enum) +#undef CASE_SET + } } + (BOOL)resolveInstanceMethod:(SEL)sel { @@ -4814,29 +3046,31 @@ static BOOL IvarSetEnum(GPBFieldDescriptor *field, void *voidContext) { 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. + // NOTE: hasOrCountSel_/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}; + ResolveIvarAccessorMethodResult result = {NULL, NULL}; for (GPBFieldDescriptor *field in descriptor->fields_) { BOOL isMapOrArray = GPBFieldIsMapOrArray(field); if (!isMapOrArray) { + // Single fields. if (sel == field->getSel_) { - static const GPBApplyStrictFunctions funcs = - GPBAPPLY_STRICT_FUNCTIONS_INIT(IvarGet); - funcs[GPBGetFieldType(field)](field, &context); + ResolveIvarGet(field, &result); break; - } else if (sel == field->hasSel_) { + } else if (sel == field->setSel_) { + ResolveIvarSet(field, descriptor.file.syntax, &result); + break; + } else if (sel == field->hasOrCountSel_) { int32_t index = GPBFieldHasIndex(field); uint32_t fieldNum = GPBFieldNumber(field); - context.impToAdd = imp_implementationWithBlock(^(id obj) { + result.impToAdd = imp_implementationWithBlock(^(id obj) { return GPBGetHasIvar(obj, index, fieldNum); }); - context.encodingSelector = @selector(getBool); + result.encodingSelector = @selector(getBool); break; } else if (sel == field->setHasSel_) { - context.impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) { + result.impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) { if (value) { [NSException raise:NSInvalidArgumentException format:@"%@: %@ can only be set to NO (to clear field).", @@ -4845,53 +3079,60 @@ static BOOL IvarSetEnum(GPBFieldDescriptor *field, void *voidContext) { } 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); + result.encodingSelector = @selector(setBool:); break; } else { GPBOneofDescriptor *oneof = field->containingOneof_; if (oneof && (sel == oneof->caseSel_)) { int32_t index = oneof->oneofDescription_->index; - context.impToAdd = imp_implementationWithBlock(^(id obj) { + result.impToAdd = imp_implementationWithBlock(^(id obj) { return GPBGetHasOneof(obj, index); }); - context.encodingSelector = @selector(getEnum); + result.encodingSelector = @selector(getEnum); break; } } } else { + // map<>/repeated fields. if (sel == field->getSel_) { if (field.fieldType == GPBFieldTypeRepeated) { - context.impToAdd = imp_implementationWithBlock(^(id obj) { + result.impToAdd = imp_implementationWithBlock(^(id obj) { return GetArrayIvarWithField(obj, field); }); } else { - context.impToAdd = imp_implementationWithBlock(^(id obj) { + result.impToAdd = imp_implementationWithBlock(^(id obj) { return GetMapIvarWithField(obj, field); }); } - context.encodingSelector = @selector(getArray); + result.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) { + // Local for syntax so the block can directly capture it and not the + // full lookup. + const GPBFileSyntax syntax = descriptor.file.syntax; + result.impToAdd = imp_implementationWithBlock(^(id obj, id value) { return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax); }); - context.encodingSelector = @selector(setArray:); + result.encodingSelector = @selector(setArray:); + break; + } else if (sel == field->hasOrCountSel_) { + result.impToAdd = imp_implementationWithBlock(^(id obj) { + // Type doesn't matter, all *Array and *Dictionary types support + // -count. + NSArray *arrayOrMap = + GPBGetObjectIvarWithFieldNoAutocreate(obj, field); + return [arrayOrMap count]; + }); + result.encodingSelector = @selector(getArrayCount); break; } } } - if (context.impToAdd) { + if (result.impToAdd) { const char *encoding = - GPBMessageEncodingForSelector(context.encodingSelector, YES); + GPBMessageEncodingForSelector(result.encodingSelector, YES); BOOL methodAdded = class_addMethod(descriptor.messageClass, sel, - context.impToAdd, encoding); + result.impToAdd, encoding); return methodAdded; } return [super resolveInstanceMethod:sel]; diff --git a/objectivec/GPBMessage_PackagePrivate.h b/objectivec/GPBMessage_PackagePrivate.h index c437c55b..d4c3501a 100644 --- a/objectivec/GPBMessage_PackagePrivate.h +++ b/objectivec/GPBMessage_PackagePrivate.h @@ -67,9 +67,9 @@ typedef struct GPBMessage_Storage *GPBMessage_StoragePtr; // 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; +- (id)getExistingExtension:(GPBExtensionDescriptor *)extension; -// Returns an array of GPBExtensionField* for all the extensions currently +// Returns an array of GPBExtensionDescriptor* for all the extensions currently // in use on the message. They are sorted by field number. - (NSArray *)sortedExtensionsInUse; diff --git a/objectivec/GPBProtocolBuffers.h b/objectivec/GPBProtocolBuffers.h index 436c9836..a66f295e 100644 --- a/objectivec/GPBProtocolBuffers.h +++ b/objectivec/GPBProtocolBuffers.h @@ -35,11 +35,10 @@ #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 "GPBUnknownField.h" #import "GPBUnknownFieldSet.h" #import "GPBUtilities.h" #import "GPBWireFormat.h" diff --git a/objectivec/GPBProtocolBuffers.m b/objectivec/GPBProtocolBuffers.m index 96eeb1d3..e9cbfb42 100644 --- a/objectivec/GPBProtocolBuffers.m +++ b/objectivec/GPBProtocolBuffers.m @@ -36,14 +36,27 @@ #import "GPBCodedOutputStream.m" #import "GPBDescriptor.m" #import "GPBDictionary.m" -#import "GPBExtensionField.m" +#import "GPBExtensionInternals.m" #import "GPBExtensionRegistry.m" -#import "GPBField.m" #import "GPBMessage.m" #import "GPBRootObject.m" +#import "GPBUnknownField.m" #import "GPBUnknownFieldSet.m" #import "GPBUtilities.m" #import "GPBWellKnownTypes.m" #import "GPBWireFormat.m" #import "google/protobuf/Descriptor.pbobjc.m" + +// Duration and Timestamp are #imported into GPBWellKnownTypes.m to the +// Objective C categories added will always be linked in with the classes. +#import "google/protobuf/Any.pbobjc.m" +#import "google/protobuf/Api.pbobjc.m" +// #import "google/protobuf/Duration.pbobjc.m" +#import "google/protobuf/Empty.pbobjc.m" +#import "google/protobuf/FieldMask.pbobjc.m" +#import "google/protobuf/SourceContext.pbobjc.m" +#import "google/protobuf/Struct.pbobjc.m" +// #import "google/protobuf/Timestamp.pbobjc.m" +#import "google/protobuf/Type.pbobjc.m" +#import "google/protobuf/Wrappers.pbobjc.m" diff --git a/objectivec/GPBProtocolBuffers_RuntimeSupport.h b/objectivec/GPBProtocolBuffers_RuntimeSupport.h index 7fd7b4c8..fea75b93 100644 --- a/objectivec/GPBProtocolBuffers_RuntimeSupport.h +++ b/objectivec/GPBProtocolBuffers_RuntimeSupport.h @@ -34,8 +34,7 @@ #import "GPBProtocolBuffers.h" #import "GPBDescriptor_PackagePrivate.h" -#import "GPBExtensionField_PackagePrivate.h" -#import "GPBExtensionRegistry.h" +#import "GPBExtensionInternals.h" #import "GPBMessage_PackagePrivate.h" #import "GPBRootObject_PackagePrivate.h" #import "GPBUtilities_PackagePrivate.h" diff --git a/objectivec/GPBRootObject.h b/objectivec/GPBRootObject.h index 2904162e..e2af5d97 100644 --- a/objectivec/GPBRootObject.h +++ b/objectivec/GPBRootObject.h @@ -32,6 +32,8 @@ @class GPBExtensionRegistry; +NS_ASSUME_NONNULL_BEGIN + // All Root Objects derive from GPBRootObject. It supplies a registry // for derived classes to register their extensions to. @interface GPBRootObject : NSObject @@ -40,3 +42,5 @@ + (GPBExtensionRegistry *)extensionRegistry; @end + +NS_ASSUME_NONNULL_END diff --git a/objectivec/GPBRootObject.m b/objectivec/GPBRootObject.m index 38dab665..7036723f 100644 --- a/objectivec/GPBRootObject.m +++ b/objectivec/GPBRootObject.m @@ -36,7 +36,7 @@ #import <CoreFoundation/CoreFoundation.h> #import "GPBDescriptor.h" -#import "GPBExtensionField.h" +#import "GPBExtensionRegistry.h" #import "GPBUtilities_PackagePrivate.h" @interface GPBExtensionDescriptor (GPBRootObject) @@ -98,6 +98,7 @@ static CFHashCode GPBRootExtensionKeyHash(const void *value) { static OSSpinLock gExtensionSingletonDictionaryLock_ = OS_SPINLOCK_INIT; static CFMutableDictionaryRef gExtensionSingletonDictionary = NULL; +static GPBExtensionRegistry *gDefaultExtensionRegistry = NULL; + (void)initialize { // Ensure the global is started up. @@ -114,6 +115,7 @@ static CFMutableDictionaryRef gExtensionSingletonDictionary = NULL; gExtensionSingletonDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallBacks, &kCFTypeDictionaryValueCallBacks); + gDefaultExtensionRegistry = [[GPBExtensionRegistry alloc] init]; } if ([self superclass] == [GPBRootObject class]) { @@ -127,17 +129,17 @@ static CFMutableDictionaryRef gExtensionSingletonDictionary = NULL; + (GPBExtensionRegistry *)extensionRegistry { // Is overridden in all the subclasses that provide extensions to provide the // per class one. - return nil; + return gDefaultExtensionRegistry; } -+ (void)globallyRegisterExtension:(GPBExtensionField *)field { - const char *key = [field.descriptor singletonNameC]; ++ (void)globallyRegisterExtension:(GPBExtensionDescriptor *)field { + const char *key = [field singletonNameC]; OSSpinLockLock(&gExtensionSingletonDictionaryLock_); CFDictionarySetValue(gExtensionSingletonDictionary, key, field); OSSpinLockUnlock(&gExtensionSingletonDictionaryLock_); } -GPB_INLINE id ExtensionForName(id self, SEL _cmd) { +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. diff --git a/objectivec/GPBRootObject_PackagePrivate.h b/objectivec/GPBRootObject_PackagePrivate.h index f1cfe990..3c8f09c8 100644 --- a/objectivec/GPBRootObject_PackagePrivate.h +++ b/objectivec/GPBRootObject_PackagePrivate.h @@ -32,12 +32,12 @@ #import "GPBRootObject.h" -@class GPBExtensionField; +@class GPBExtensionDescriptor; @interface GPBRootObject () // Globally register. -+ (void)globallyRegisterExtension:(GPBExtensionField *)field; ++ (void)globallyRegisterExtension:(GPBExtensionDescriptor *)field; @end diff --git a/objectivec/GPBTypes.h b/objectivec/GPBRuntimeTypes.h index 49c2b9e4..e91d86a6 100644 --- a/objectivec/GPBTypes.h +++ b/objectivec/GPBRuntimeTypes.h @@ -63,36 +63,36 @@ typedef union { GPB_UNSAFE_UNRETAINED NSString *valueString; GPB_UNSAFE_UNRETAINED GPBMessage *valueMessage; int32_t valueEnum; -} GPBValue; +} GPBGenericValue; // 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; + GPBDataTypeBool = 0, + GPBDataTypeFixed32, + GPBDataTypeSFixed32, + GPBDataTypeFloat, + GPBDataTypeFixed64, + GPBDataTypeSFixed64, + GPBDataTypeDouble, + GPBDataTypeInt32, + GPBDataTypeInt64, + GPBDataTypeSInt32, + GPBDataTypeSInt64, + GPBDataTypeUInt32, + GPBDataTypeUInt64, + GPBDataTypeBytes, + GPBDataTypeString, + GPBDataTypeMessage, + GPBDataTypeGroup, + GPBDataTypeEnum, +} GPBDataType; 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 + // A count of the number of types in GPBDataType. Separated out from the + // GPBDataType enum to avoid warnings regarding not handling + // GPBDataType_Count in switch statements. + GPBDataType_Count = GPBDataTypeEnum + 1 }; // An extension range. diff --git a/objectivec/GPBField.h b/objectivec/GPBUnknownField.h index 041a242f..12d72a9a 100644 --- a/objectivec/GPBField.h +++ b/objectivec/GPBUnknownField.h @@ -35,7 +35,9 @@ @class GPBUInt64Array; @class GPBUnknownFieldSet; -@interface GPBField : NSObject<NSCopying> +NS_ASSUME_NONNULL_BEGIN + +@interface GPBUnknownField : NSObject<NSCopying> @property(nonatomic, readonly, assign) int32_t number; @@ -43,8 +45,8 @@ @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; +@property(nonatomic, readonly, strong) NSArray *lengthDelimitedList; // NSData +@property(nonatomic, readonly, strong) NSArray *groupList; // GPBUnknownFieldSet // Only one of these should be used per Field. - (void)addVarint:(uint64_t)value; @@ -54,3 +56,5 @@ - (void)addGroup:(GPBUnknownFieldSet *)value; @end + +NS_ASSUME_NONNULL_END diff --git a/objectivec/GPBField.m b/objectivec/GPBUnknownField.m index c390ae9e..c49c0dfc 100644 --- a/objectivec/GPBField.m +++ b/objectivec/GPBUnknownField.m @@ -28,12 +28,12 @@ // (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 "GPBUnknownField_PackagePrivate.h" #import "GPBArray.h" #import "GPBCodedOutputStream.h" -@interface GPBField () { +@implementation GPBUnknownField { @protected int32_t number_; GPBUInt64Array *mutableVarintList_; @@ -42,9 +42,6 @@ NSMutableArray *mutableLengthDelimitedList_; NSMutableArray *mutableGroupList_; } -@end - -@implementation GPBField @synthesize number = number_; @synthesize varintList = mutableVarintList_; @@ -71,7 +68,8 @@ } - (id)copyWithZone:(NSZone *)zone { - GPBField *result = [[GPBField allocWithZone:zone] initWithNumber:number_]; + GPBUnknownField *result = + [[GPBUnknownField allocWithZone:zone] initWithNumber:number_]; result->mutableFixed32List_ = [mutableFixed32List_ copyWithZone:zone]; result->mutableFixed64List_ = [mutableFixed64List_ copyWithZone:zone]; result->mutableLengthDelimitedList_ = @@ -91,8 +89,8 @@ - (BOOL)isEqual:(id)object { if (self == object) return YES; - if (![object isKindOfClass:[GPBField class]]) return NO; - GPBField *field = (GPBField *)object; + if (![object isKindOfClass:[GPBUnknownField class]]) return NO; + GPBUnknownField *field = (GPBUnknownField *)object; BOOL equalVarint = (mutableVarintList_.count == 0 && field->mutableVarintList_.count == 0) || [mutableVarintList_ isEqual:field->mutableVarintList_]; @@ -131,23 +129,23 @@ - (void)writeToOutput:(GPBCodedOutputStream *)output { NSUInteger count = mutableVarintList_.count; if (count > 0) { - [output writeUInt64s:number_ values:mutableVarintList_ tag:0]; + [output writeUInt64Array:number_ values:mutableVarintList_ tag:0]; } count = mutableFixed32List_.count; if (count > 0) { - [output writeFixed32s:number_ values:mutableFixed32List_ tag:0]; + [output writeFixed32Array:number_ values:mutableFixed32List_ tag:0]; } count = mutableFixed64List_.count; if (count > 0) { - [output writeFixed64s:number_ values:mutableFixed64List_ tag:0]; + [output writeFixed64Array:number_ values:mutableFixed64List_ tag:0]; } count = mutableLengthDelimitedList_.count; if (count > 0) { - [output writeDatas:number_ values:mutableLengthDelimitedList_]; + [output writeBytesArray:number_ values:mutableLengthDelimitedList_]; } count = mutableGroupList_.count; if (count > 0) { - [output writeUnknownGroups:number_ values:mutableGroupList_]; + [output writeUnknownGroupArray:number_ values:mutableGroupList_]; } } @@ -173,7 +171,7 @@ }]; for (NSData *data in mutableLengthDelimitedList_) { - result += GPBComputeDataSize(number, data); + result += GPBComputeBytesSize(number, data); } for (GPBUnknownFieldSet *set in mutableGroupList_) { @@ -229,7 +227,7 @@ return description; } -- (void)mergeFromField:(GPBField *)other { +- (void)mergeFromField:(GPBUnknownField *)other { GPBUInt64Array *otherVarintList = other.varintList; if (otherVarintList.count > 0) { if (mutableVarintList_ == nil) { diff --git a/objectivec/GPBUnknownFieldSet.h b/objectivec/GPBUnknownFieldSet.h index 48824f10..d785ca16 100644 --- a/objectivec/GPBUnknownFieldSet.h +++ b/objectivec/GPBUnknownFieldSet.h @@ -30,17 +30,21 @@ #import <Foundation/Foundation.h> -@class GPBField; +@class GPBUnknownField; + +NS_ASSUME_NONNULL_BEGIN @interface GPBUnknownFieldSet : NSObject<NSCopying> - (BOOL)hasField:(int32_t)number; -- (GPBField *)getField:(int32_t)number; +- (nullable GPBUnknownField *)getField:(int32_t)number; - (NSUInteger)countOfFields; -- (void)addField:(GPBField *)field; +- (void)addField:(GPBUnknownField *)field; // Returns an NSArray of the GPBFields sorted by the field numbers. - (NSArray *)sortedFields; @end + +NS_ASSUME_NONNULL_END diff --git a/objectivec/GPBUnknownFieldSet.m b/objectivec/GPBUnknownFieldSet.m index d7154dc8..4ddc0d2a 100644 --- a/objectivec/GPBUnknownFieldSet.m +++ b/objectivec/GPBUnknownFieldSet.m @@ -32,7 +32,7 @@ #import "GPBCodedInputStream_PackagePrivate.h" #import "GPBCodedOutputStream.h" -#import "GPBField_PackagePrivate.h" +#import "GPBUnknownField_PackagePrivate.h" #import "GPBUtilities.h" #import "GPBWireFormat.h" @@ -85,10 +85,10 @@ static void checkNumber(int32_t number) { static void CopyWorker(const void *key, const void *value, void *context) { #pragma unused(key) - GPBField *field = value; + GPBUnknownField *field = value; GPBUnknownFieldSet *result = context; - GPBField *copied = [field copy]; + GPBUnknownField *copied = [field copy]; [result addField:copied]; [copied release]; } @@ -136,9 +136,10 @@ static void CopyWorker(const void *key, const void *value, void *context) { return fields_ ? (CFDictionaryGetValue(fields_, (void *)key) != nil) : NO; } -- (GPBField *)getField:(int32_t)number { +- (GPBUnknownField *)getField:(int32_t)number { ssize_t key = number; - GPBField *result = fields_ ? CFDictionaryGetValue(fields_, (void *)key) : nil; + GPBUnknownField *result = + fields_ ? CFDictionaryGetValue(fields_, (void *)key) : nil; return result; } @@ -150,12 +151,12 @@ static void CopyWorker(const void *key, const void *value, void *context) { if (!fields_) return nil; size_t count = CFDictionaryGetCount(fields_); ssize_t keys[count]; - GPBField *values[count]; + GPBUnknownField *values[count]; CFDictionaryGetKeysAndValues(fields_, (const void **)keys, (const void **)values); struct GPBFieldPair { ssize_t key; - GPBField *value; + GPBUnknownField *value; } pairs[count]; for (size_t i = 0; i < count; ++i) { pairs[i].key = keys[i]; @@ -179,13 +180,13 @@ static void CopyWorker(const void *key, const void *value, void *context) { if (!fields_) return; size_t count = CFDictionaryGetCount(fields_); ssize_t keys[count]; - GPBField *values[count]; + GPBUnknownField *values[count]; CFDictionaryGetKeysAndValues(fields_, (const void **)keys, (const void **)values); if (count > 1) { struct GPBFieldPair { ssize_t key; - GPBField *value; + GPBUnknownField *value; } pairs[count]; for (size_t i = 0; i < count; ++i) { @@ -199,7 +200,7 @@ static void CopyWorker(const void *key, const void *value, void *context) { 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; + GPBUnknownField *value = pairs[i].value; [value writeToOutput:output]; } } else { @@ -219,7 +220,7 @@ static void CopyWorker(const void *key, const void *value, void *context) { static void GPBUnknownFieldSetSerializedSize(const void *key, const void *value, void *context) { #pragma unused(key) - GPBField *field = value; + GPBUnknownField *field = value; size_t *result = context; *result += [field serializedSize]; } @@ -237,7 +238,7 @@ static void GPBUnknownFieldSetWriteAsMessageSetTo(const void *key, const void *value, void *context) { #pragma unused(key) - GPBField *field = value; + GPBUnknownField *field = value; GPBCodedOutputStream *output = context; [field writeAsMessageSetExtensionToOutput:output]; } @@ -253,7 +254,7 @@ static void GPBUnknownFieldSetSerializedSizeAsMessageSet(const void *key, const void *value, void *context) { #pragma unused(key) - GPBField *field = value; + GPBUnknownField *field = value; size_t *result = context; *result += [field serializedSizeAsMessageSetExtension]; } @@ -280,7 +281,7 @@ static void GPBUnknownFieldSetSerializedSizeAsMessageSet(const void *key, return GPBWireFormatGetTagWireType(tag) != GPBWireFormatEndGroup; } -- (void)addField:(GPBField *)field { +- (void)addField:(GPBUnknownField *)field { int32_t number = [field number]; checkNumber(number); if (!fields_) { @@ -297,12 +298,12 @@ static void GPBUnknownFieldSetSerializedSizeAsMessageSet(const void *key, CFDictionarySetValue(fields_, (const void *)key, field); } -- (GPBField *)mutableFieldForNumber:(int32_t)number create:(BOOL)create { +- (GPBUnknownField *)mutableFieldForNumber:(int32_t)number create:(BOOL)create { ssize_t key = number; - GPBField *existing = + GPBUnknownField *existing = fields_ ? CFDictionaryGetValue(fields_, (const void *)key) : nil; if (!existing && create) { - existing = [[GPBField alloc] initWithNumber:number]; + existing = [[GPBUnknownField alloc] initWithNumber:number]; // This retains existing. [self addField:existing]; [existing release]; @@ -314,19 +315,19 @@ static void GPBUnknownFieldSetMergeUnknownFields(const void *key, const void *value, void *context) { #pragma unused(key) - GPBField *field = value; + GPBUnknownField *field = value; GPBUnknownFieldSet *self = context; int32_t number = [field number]; checkNumber(number); - GPBField *oldField = [self mutableFieldForNumber:number create:NO]; + GPBUnknownField *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]; + GPBUnknownField *fieldCopy = [field copy]; [self addField:fieldCopy]; [fieldCopy release]; } @@ -356,18 +357,18 @@ static void GPBUnknownFieldSetMergeUnknownFields(const void *key, GPBCodedInputStreamState *state = &input->state_; switch (GPBWireFormatGetTagWireType(tag)) { case GPBWireFormatVarint: { - GPBField *field = [self mutableFieldForNumber:number create:YES]; + GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; [field addVarint:GPBCodedInputStreamReadInt64(state)]; return YES; } case GPBWireFormatFixed64: { - GPBField *field = [self mutableFieldForNumber:number create:YES]; + GPBUnknownField *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]; + NSData *data = GPBCodedInputStreamReadRetainedBytes(state); + GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; [field addLengthDelimited:data]; [data release]; return YES; @@ -375,7 +376,7 @@ static void GPBUnknownFieldSetMergeUnknownFields(const void *key, case GPBWireFormatStartGroup: { GPBUnknownFieldSet *unknownFieldSet = [[GPBUnknownFieldSet alloc] init]; [input readUnknownGroup:number message:unknownFieldSet]; - GPBField *field = [self mutableFieldForNumber:number create:YES]; + GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; [field addGroup:unknownFieldSet]; [unknownFieldSet release]; return YES; @@ -383,7 +384,7 @@ static void GPBUnknownFieldSetMergeUnknownFields(const void *key, case GPBWireFormatEndGroup: return NO; case GPBWireFormatFixed32: { - GPBField *field = [self mutableFieldForNumber:number create:YES]; + GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; [field addFixed32:GPBCodedInputStreamReadFixed32(state)]; return YES; } @@ -396,7 +397,7 @@ static void GPBUnknownFieldSetMergeUnknownFields(const void *key, } - (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data { - GPBField *field = [self mutableFieldForNumber:fieldNum create:YES]; + GPBUnknownField *field = [self mutableFieldForNumber:fieldNum create:YES]; [field addLengthDelimited:data]; } diff --git a/objectivec/GPBField_PackagePrivate.h b/objectivec/GPBUnknownField_PackagePrivate.h index 73c1fa80..1fbce0f9 100644 --- a/objectivec/GPBField_PackagePrivate.h +++ b/objectivec/GPBUnknownField_PackagePrivate.h @@ -30,11 +30,11 @@ #import <Foundation/Foundation.h> -#import "GPBField.h" +#import "GPBUnknownField.h" @class GPBCodedOutputStream; -@interface GPBField () +@interface GPBUnknownField () - (instancetype)initWithNumber:(int32_t)number; @@ -44,6 +44,6 @@ - (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output; - (size_t)serializedSizeAsMessageSetExtension; -- (void)mergeFromField:(GPBField *)other; +- (void)mergeFromField:(GPBUnknownField *)other; @end diff --git a/objectivec/GPBUtilities.h b/objectivec/GPBUtilities.h index 8813f1ad..1301b436 100644 --- a/objectivec/GPBUtilities.h +++ b/objectivec/GPBUtilities.h @@ -30,152 +30,158 @@ #import <Foundation/Foundation.h> +#import "GPBArray.h" #import "GPBMessage.h" -#import "GPBTypes.h" +#import "GPBRuntimeTypes.h" CF_EXTERN_C_BEGIN +NS_ASSUME_NONNULL_BEGIN + +// Generates a string 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 * __nullable lineIndent); +NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet, + NSString * __nullable lineIndent); + +// +// Test if the given field is set on a message. +// BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber); BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field); +// +// Clear the given field of a message. +// void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field); +//%PDDM-EXPAND GPB_ACCESSORS() +// This block of code is generated, do not edit it directly. + + +// +// Get/Set the given field of a message. +// + +// Single Fields + +NSData *GPBGetMessageBytesField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageBytesField(GPBMessage *self, GPBFieldDescriptor *field, NSData *value); + +NSString *GPBGetMessageStringField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageStringField(GPBMessage *self, GPBFieldDescriptor *field, NSString *value); + +GPBMessage *GPBGetMessageMessageField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageMessageField(GPBMessage *self, GPBFieldDescriptor *field, GPBMessage *value); + +GPBMessage *GPBGetMessageGroupField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageGroupField(GPBMessage *self, GPBFieldDescriptor *field, GPBMessage *value); + +BOOL GPBGetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field, BOOL value); + +int32_t GPBGetMessageInt32Field(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageInt32Field(GPBMessage *self, GPBFieldDescriptor *field, int32_t value); + +uint32_t GPBGetMessageUInt32Field(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageUInt32Field(GPBMessage *self, GPBFieldDescriptor *field, uint32_t value); + +int64_t GPBGetMessageInt64Field(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageInt64Field(GPBMessage *self, GPBFieldDescriptor *field, int64_t value); + +uint64_t GPBGetMessageUInt64Field(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageUInt64Field(GPBMessage *self, GPBFieldDescriptor *field, uint64_t value); + +float GPBGetMessageFloatField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageFloatField(GPBMessage *self, GPBFieldDescriptor *field, float value); + +double GPBGetMessageDoubleField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageDoubleField(GPBMessage *self, GPBFieldDescriptor *field, double value); + +// Get/Set the given enum field of a message. You can only Set values that are +// members of the enum. For proto3, when doing a Get, if the value isn't a +// memeber of the enum, kGPBUnrecognizedEnumeratorValue will be returned. The +// the functions with "Raw" in the will bypass all checks. +int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value); +int32_t GPBGetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value); + +// Repeated Fields + +// The object will/should be GPB*Array or NSMutableArray based on the field's +// type. +id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array); + +// Map Fields + +// The object will/should be GPB*Dictionary or NSMutableDictionary based on the +// field's type. +id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, id dictionary); + +//%PDDM-EXPAND-END GPB_ACCESSORS() + // 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); +NS_ASSUME_NONNULL_END CF_EXTERN_C_END -//%PDDM-DEFINE GPB_IVAR_ACCESSORS() -//%// Getters and Setters for ivars named |name| from instance self. + +//%PDDM-DEFINE GPB_ACCESSORS() +//% +//%// +//%// Get/Set the given field of a message. +//%// +//% +//%// Single Fields +//% +//%GPB_ACCESSOR_SINGLE_FULL(Bytes, NSData, *) +//%GPB_ACCESSOR_SINGLE_FULL(String, NSString, *) +//%GPB_ACCESSOR_SINGLE_FULL(Message, GPBMessage, *) +//%GPB_ACCESSOR_SINGLE_FULL(Group, GPBMessage, *) +//%GPB_ACCESSOR_SINGLE(Bool, BOOL) +//%GPB_ACCESSOR_SINGLE(Int32, int32_t) +//%GPB_ACCESSOR_SINGLE(UInt32, uint32_t) +//%GPB_ACCESSOR_SINGLE(Int64, int64_t) +//%GPB_ACCESSOR_SINGLE(UInt64, uint64_t) +//%GPB_ACCESSOR_SINGLE(Float, float) +//%GPB_ACCESSOR_SINGLE(Double, double) +//%// Get/Set the given enum field of a message. You can only Set values that are +//%// members of the enum. For proto3, when doing a Get, if the value isn't a +//%// memeber of the enum, kGPBUnrecognizedEnumeratorValue will be returned. The +//%// the functions with "Raw" in the will bypass all checks. +//%int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field); +//%void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value); +//%int32_t GPBGetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field); +//%void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value); +//% +//%// Repeated Fields +//% +//%// The object will/should be GPB*Array or NSMutableArray based on the field's +//%// type. +//%id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field); +//%void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array); +//% +//%// Map Fields +//% +//%// The object will/should be GPB*Dictionary or NSMutableDictionary based on the +//%// field's type. +//%id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field); +//%void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, id dictionary); +//% + +//%PDDM-DEFINE GPB_ACCESSOR_SINGLE(NAME, TYPE) +//%GPB_ACCESSOR_SINGLE_FULL(NAME, TYPE, ) +//%PDDM-DEFINE GPB_ACCESSOR_SINGLE_FULL(NAME, TYPE, TisP) +//%TYPE TisP##GPBGetMessage##NAME##Field(GPBMessage *self, GPBFieldDescriptor *field); +//%void GPBSetMessage##NAME##Field(GPBMessage *self, GPBFieldDescriptor *field, TYPE TisP##value); //% -//%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 index f912b979..5ee61230 100644 --- a/objectivec/GPBUtilities.m +++ b/objectivec/GPBUtilities.m @@ -35,9 +35,8 @@ #import "GPBArray_PackagePrivate.h" #import "GPBDescriptor_PackagePrivate.h" #import "GPBDictionary_PackagePrivate.h" -#import "GPBExtensionField.h" -#import "GPBField.h" #import "GPBMessage_PackagePrivate.h" +#import "GPBUnknownField.h" #import "GPBUnknownFieldSet.h" static void AppendTextFormatForMessage(GPBMessage *message, @@ -53,6 +52,15 @@ NSData *GPBEmptyNSData(void) { return defaultNSData; } +void GPBCheckRuntimeVersionInternal(int32_t version) { + if (version != GOOGLE_PROTOBUF_OBJC_GEN_VERSION) { + [NSException raise:NSInternalInconsistencyException + format:@"Linked to ProtocolBuffer runtime version %d," + @" but code compiled with version %d!", + GOOGLE_PROTOBUF_OBJC_GEN_VERSION, version]; + } +} + BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber) { GPBDescriptor *descriptor = [self descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:fieldNumber]; @@ -166,8 +174,8 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, #pragma mark - IVar accessors //%PDDM-DEFINE IVAR_POD_ACCESSORS_DEFN(NAME, TYPE) -//%TYPE GPBGet##NAME##IvarWithField(GPBMessage *self, -//% TYPE$S NAME$S GPBFieldDescriptor *field) { +//%TYPE GPBGetMessage##NAME##Field(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]; @@ -178,9 +186,9 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, //%} //% //%// 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) { +//%void GPBSetMessage##NAME##Field(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); @@ -211,18 +219,18 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, //% GPBBecomeVisibleToAutocreator(self); //%} //% -//%PDDM-DEFINE IVAR_ALIAS_DEFN(NAME, ALIAS_NAME, TYPE, ALIAS_TYPE) +//%PDDM-DEFINE IVAR_ALIAS_DEFN_OBJECT(NAME, 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); +//%TYPE *GPBGetMessage##NAME##Field(GPBMessage *self, +//% TYPE$S NAME$S GPBFieldDescriptor *field) { +//% return (TYPE *)GPBGetObjectIvarWithField(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); +//%void GPBSetMessage##NAME##Field(GPBMessage *self, +//% NAME$S GPBFieldDescriptor *field, +//% NAME$S TYPE *value) { +//% GPBSetObjectIvarWithField(self, field, (id)value); //%} //% @@ -252,8 +260,8 @@ void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, } // This exists only for briging some aliased types, nothing else should use it. -GPB_INLINE void GPBSetObjectIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, id value) { +static 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], @@ -276,9 +284,9 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, #if defined(__clang_analyzer__) if (self->messageStorage_ == NULL) return; #endif - GPBType fieldType = GPBGetFieldType(field); + GPBDataType fieldType = GPBGetFieldDataType(field); BOOL isMapOrArray = GPBFieldIsMapOrArray(field); - BOOL fieldIsMessage = GPBTypeIsMessage(fieldType); + BOOL fieldIsMessage = GPBDataTypeIsMessage(fieldType); #ifdef DEBUG if (value == nil && !isMapOrArray && !fieldIsMessage && field.hasDefaultValue) { @@ -294,7 +302,7 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, // 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 *hasSel = NSStringFromSelector(field->hasOrCountSel_); NSString *propName = field.name; NSString *className = self.descriptor.name; NSLog(@"warning: '%@.%@ = nil;' is not clearly defined for fields with " @@ -302,7 +310,7 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, @"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()", + (fieldType == GPBDataTypeString) ? @"@\"\"" : @"GPBEmptyNSData()", className, hasSel, field.defaultValue.valueString); // Note: valueString, depending on the type, it could easily be // valueData/valueMessage. @@ -317,9 +325,9 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, } // 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. + // Under proto3, Bytes & 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; @@ -338,7 +346,7 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, if (isMapOrArray) { if (field.fieldType == GPBFieldTypeRepeated) { // If the old array was autocreated by us, then clear it. - if (GPBTypeIsObject(fieldType)) { + if (GPBDataTypeIsObject(fieldType)) { GPBAutocreatedArray *autoArray = oldValue; if (autoArray->_autocreator == self) { autoArray->_autocreator = nil; @@ -352,8 +360,8 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, } } else { // GPBFieldTypeMap // If the old map was autocreated by us, then clear it. - if ((field.mapKeyType == GPBTypeString) && - GPBTypeIsObject(fieldType)) { + if ((field.mapKeyDataType == GPBDataTypeString) && + GPBDataTypeIsObject(fieldType)) { GPBAutocreatedDictionary *autoDict = oldValue; if (autoDict->_autocreator == self) { autoDict->_autocreator = nil; @@ -399,7 +407,7 @@ id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { // Not set... // Non messages (string/data), get their default. - if (!GPBFieldTypeIsMessage(field)) { + if (!GPBFieldDataTypeIsMessage(field)) { return field.defaultValue.valueMessage; } @@ -417,7 +425,7 @@ id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { } // Only exists for public api, no core code should use this. -int32_t GPBGetEnumIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { +int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field) { GPBFileSyntax syntax = [self descriptor].file.syntax; return GPBGetEnumIvarWithFieldInternal(self, field, syntax); } @@ -425,9 +433,9 @@ int32_t GPBGetEnumIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { 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. + int32_t result = GPBGetMessageInt32Field(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; @@ -436,8 +444,8 @@ int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self, } // Only exists for public api, no core code should use this. -void GPBSetEnumIvarWithField(GPBMessage *self, GPBFieldDescriptor *field, - int32_t value) { +void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, + int32_t value) { GPBFileSyntax syntax = [self descriptor].file.syntax; GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); } @@ -454,11 +462,25 @@ void GPBSetEnumIvarWithFieldInternal(GPBMessage *self, GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); } +// Only exists for public api, no core code should use this. +int32_t GPBGetMessageRawEnumField(GPBMessage *self, + GPBFieldDescriptor *field) { + int32_t result = GPBGetMessageInt32Field(self, field); + return result; +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, + int32_t value) { + GPBFileSyntax syntax = [self descriptor].file.syntax; + 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) { +BOOL GPBGetMessageBoolField(GPBMessage *self, + GPBFieldDescriptor *field) { if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; BOOL *typePtr = (BOOL *)&storage[field->description_->offset]; @@ -469,9 +491,9 @@ BOOL GPBGetBoolIvarWithField(GPBMessage *self, } // Only exists for public api, no core code should use this. -void GPBSetBoolIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - BOOL value) { +void GPBSetMessageBoolField(GPBMessage *self, + GPBFieldDescriptor *field, + BOOL value) { if (self == nil || field == nil) return; GPBFileSyntax syntax = [self descriptor].file.syntax; GPBSetBoolIvarWithFieldInternal(self, field, value, syntax); @@ -505,8 +527,8 @@ void GPBSetBoolIvarWithFieldInternal(GPBMessage *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) { +int32_t GPBGetMessageInt32Field(GPBMessage *self, + GPBFieldDescriptor *field) { if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; int32_t *typePtr = (int32_t *)&storage[field->description_->offset]; @@ -517,9 +539,9 @@ int32_t GPBGetInt32IvarWithField(GPBMessage *self, } // Only exists for public api, no core code should use this. -void GPBSetInt32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - int32_t value) { +void GPBSetMessageInt32Field(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value) { if (self == nil || field == nil) return; GPBFileSyntax syntax = [self descriptor].file.syntax; GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); @@ -553,8 +575,8 @@ void GPBSetInt32IvarWithFieldInternal(GPBMessage *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) { +uint32_t GPBGetMessageUInt32Field(GPBMessage *self, + GPBFieldDescriptor *field) { if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset]; @@ -565,9 +587,9 @@ uint32_t GPBGetUInt32IvarWithField(GPBMessage *self, } // Only exists for public api, no core code should use this. -void GPBSetUInt32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - uint32_t value) { +void GPBSetMessageUInt32Field(GPBMessage *self, + GPBFieldDescriptor *field, + uint32_t value) { if (self == nil || field == nil) return; GPBFileSyntax syntax = [self descriptor].file.syntax; GPBSetUInt32IvarWithFieldInternal(self, field, value, syntax); @@ -601,8 +623,8 @@ void GPBSetUInt32IvarWithFieldInternal(GPBMessage *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) { +int64_t GPBGetMessageInt64Field(GPBMessage *self, + GPBFieldDescriptor *field) { if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; int64_t *typePtr = (int64_t *)&storage[field->description_->offset]; @@ -613,9 +635,9 @@ int64_t GPBGetInt64IvarWithField(GPBMessage *self, } // Only exists for public api, no core code should use this. -void GPBSetInt64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - int64_t value) { +void GPBSetMessageInt64Field(GPBMessage *self, + GPBFieldDescriptor *field, + int64_t value) { if (self == nil || field == nil) return; GPBFileSyntax syntax = [self descriptor].file.syntax; GPBSetInt64IvarWithFieldInternal(self, field, value, syntax); @@ -649,8 +671,8 @@ void GPBSetInt64IvarWithFieldInternal(GPBMessage *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) { +uint64_t GPBGetMessageUInt64Field(GPBMessage *self, + GPBFieldDescriptor *field) { if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset]; @@ -661,9 +683,9 @@ uint64_t GPBGetUInt64IvarWithField(GPBMessage *self, } // Only exists for public api, no core code should use this. -void GPBSetUInt64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - uint64_t value) { +void GPBSetMessageUInt64Field(GPBMessage *self, + GPBFieldDescriptor *field, + uint64_t value) { if (self == nil || field == nil) return; GPBFileSyntax syntax = [self descriptor].file.syntax; GPBSetUInt64IvarWithFieldInternal(self, field, value, syntax); @@ -697,8 +719,8 @@ void GPBSetUInt64IvarWithFieldInternal(GPBMessage *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) { +float GPBGetMessageFloatField(GPBMessage *self, + GPBFieldDescriptor *field) { if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; float *typePtr = (float *)&storage[field->description_->offset]; @@ -709,9 +731,9 @@ float GPBGetFloatIvarWithField(GPBMessage *self, } // Only exists for public api, no core code should use this. -void GPBSetFloatIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - float value) { +void GPBSetMessageFloatField(GPBMessage *self, + GPBFieldDescriptor *field, + float value) { if (self == nil || field == nil) return; GPBFileSyntax syntax = [self descriptor].file.syntax; GPBSetFloatIvarWithFieldInternal(self, field, value, syntax); @@ -745,8 +767,8 @@ void GPBSetFloatIvarWithFieldInternal(GPBMessage *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) { +double GPBGetMessageDoubleField(GPBMessage *self, + GPBFieldDescriptor *field) { if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; double *typePtr = (double *)&storage[field->description_->offset]; @@ -757,9 +779,9 @@ double GPBGetDoubleIvarWithField(GPBMessage *self, } // Only exists for public api, no core code should use this. -void GPBSetDoubleIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - double value) { +void GPBSetMessageDoubleField(GPBMessage *self, + GPBFieldDescriptor *field, + double value) { if (self == nil || field == nil) return; GPBFileSyntax syntax = [self descriptor].file.syntax; GPBSetDoubleIvarWithFieldInternal(self, field, value, syntax); @@ -794,223 +816,225 @@ void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, // 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) +//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(String, NSString) // 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); +NSString *GPBGetMessageStringField(GPBMessage *self, + GPBFieldDescriptor *field) { + return (NSString *)GPBGetObjectIvarWithField(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); +void GPBSetMessageStringField(GPBMessage *self, + GPBFieldDescriptor *field, + NSString *value) { + GPBSetObjectIvarWithField(self, field, (id)value); } -//%PDDM-EXPAND IVAR_ALIAS_DEFN(Fixed64, UInt64, uint64_t, uint64_t) +//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Bytes, NSData) // 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); +NSData *GPBGetMessageBytesField(GPBMessage *self, + GPBFieldDescriptor *field) { + return (NSData *)GPBGetObjectIvarWithField(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); +void GPBSetMessageBytesField(GPBMessage *self, + GPBFieldDescriptor *field, + NSData *value) { + GPBSetObjectIvarWithField(self, field, (id)value); } -//%PDDM-EXPAND IVAR_ALIAS_DEFN(String, Object, NSString*, id) +//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Message, GPBMessage) // 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); +GPBMessage *GPBGetMessageMessageField(GPBMessage *self, + GPBFieldDescriptor *field) { + return (GPBMessage *)GPBGetObjectIvarWithField(self, field); } // Only exists for public api, no core code should use this. -void GPBSetStringIvarWithField(GPBMessage *self, +void GPBSetMessageMessageField(GPBMessage *self, GPBFieldDescriptor *field, - NSString* value) { + GPBMessage *value) { GPBSetObjectIvarWithField(self, field, (id)value); } -//%PDDM-EXPAND IVAR_ALIAS_DEFN(Data, Object, NSData*, id) +//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Group, GPBMessage) // 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); +GPBMessage *GPBGetMessageGroupField(GPBMessage *self, + GPBFieldDescriptor *field) { + return (GPBMessage *)GPBGetObjectIvarWithField(self, field); } // Only exists for public api, no core code should use this. -void GPBSetDataIvarWithField(GPBMessage *self, +void GPBSetMessageGroupField(GPBMessage *self, GPBFieldDescriptor *field, - NSData* value) { + GPBMessage *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. +//%PDDM-EXPAND-END (4 expansions) // Only exists for public api, no core code should use this. -GPBMessage* GPBGetMessageIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field) { - return (GPBMessage*)GPBGetObjectIvarWithField(self, field); +id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field) { +#if DEBUG + if (field.fieldType != GPBFieldTypeRepeated) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@ is not a repeated field.", + [self class], field.name]; + } +#endif + return 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); +void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array) { +#if DEBUG + if (field.fieldType != GPBFieldTypeRepeated) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@ is not a repeated field.", + [self class], field.name]; + } + Class expectedClass = Nil; + switch (GPBGetFieldDataType(field)) { + case GPBDataTypeBool: + expectedClass = [GPBBoolArray class]; + break; + case GPBDataTypeSFixed32: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + expectedClass = [GPBInt32Array class]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + expectedClass = [GPBUInt32Array class]; + break; + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + expectedClass = [GPBInt64Array class]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + expectedClass = [GPBUInt64Array class]; + break; + case GPBDataTypeFloat: + expectedClass = [GPBFloatArray class]; + break; + case GPBDataTypeDouble: + expectedClass = [GPBDoubleArray class]; + break; + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: + expectedClass = [NSMutableDictionary class]; + break; + case GPBDataTypeEnum: + expectedClass = [GPBBoolArray class]; + break; + } + if (array && ![array isKindOfClass:expectedClass]) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@: Expected %@ object, got %@.", + [self class], field.name, expectedClass, [array class]]; + } +#endif + GPBSetObjectIvarWithField(self, field, array); +} + +#if DEBUG +static NSString *TypeToStr(GPBDataType dataType) { + switch (dataType) { + case GPBDataTypeBool: + return @"Bool"; + case GPBDataTypeSFixed32: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + return @"Int32"; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + return @"UInt32"; + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + return @"Int64"; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + return @"UInt64"; + case GPBDataTypeFloat: + return @"Float"; + case GPBDataTypeDouble: + return @"Double"; + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: + return @"Object"; + case GPBDataTypeEnum: + return @"Bool"; + } } - -//%PDDM-EXPAND IVAR_ALIAS_DEFN(Group, Object, GPBMessage*, id) -// This block of code is generated, do not edit it directly. +#endif // Only exists for public api, no core code should use this. -GPBMessage* GPBGetGroupIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field) { - return (GPBMessage*)GPBGetObjectIvarWithField(self, field); +id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field) { +#if DEBUG + if (field.fieldType != GPBFieldTypeMap) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@ is not a map<> field.", + [self class], field.name]; + } +#endif + return 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); +void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, + id dictionary) { +#if DEBUG + if (field.fieldType != GPBFieldTypeMap) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@ is not a map<> field.", + [self class], field.name]; + } + if (dictionary) { + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSString *keyStr = TypeToStr(keyDataType); + NSString *valueStr = TypeToStr(valueDataType); + if (keyDataType == GPBDataTypeString) { + keyStr = @"String"; + } + Class expectedClass = Nil; + if ((keyDataType == GPBDataTypeString) && + GPBDataTypeIsObject(valueDataType)) { + expectedClass = [NSMutableDictionary class]; } else { - wasGood = GPBApplyFunctionsBasedOnField(field, functions, context); + NSString *className = + [NSString stringWithFormat:@"GPB%@%@Dictionary", keyStr, valueStr]; + expectedClass = NSClassFromString(className); + NSCAssert(expectedClass, @"Missing a class (%@)?", expectedClass); } - if (!wasGood) { - break; + if (![dictionary isKindOfClass:expectedClass]) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@: Expected %@ object, got %@.", + [self class], field.name, expectedClass, + [dictionary class]]; } } +#endif + GPBSetObjectIvarWithField(self, field, dictionary); } -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; - } - } -} +#pragma mark - Misc Dynamic Runtime Utils const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel) { Protocol *protocol = @@ -1072,9 +1096,9 @@ static void AppendBufferAsString(NSData *buffer, NSMutableString *destStr) { 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); + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + BOOL isMessageValue = GPBDataTypeIsMessage(valueDataType); NSString *msgStartFirst = [NSString stringWithFormat:@"%@%@ {%@\n", lineIndent, fieldName, lineEnding]; @@ -1088,7 +1112,8 @@ static void AppendTextFormatForMapMessageField( __block BOOL isFirst = YES; - if ((keyType == GPBTypeString) && GPBTypeIsObject(valueType)) { + if ((keyDataType == GPBDataTypeString) && + GPBDataTypeIsObject(valueDataType)) { // map is an NSDictionary. NSDictionary *dict = map; [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) { @@ -1101,16 +1126,16 @@ static void AppendTextFormatForMapMessageField( [toStr appendString:@"\n"]; [toStr appendString:valueLine]; - switch (valueType) { - case GPBTypeString: + switch (valueDataType) { + case GPBDataTypeString: AppendStringEscaped(value, toStr); break; - case GPBTypeData: + case GPBDataTypeBytes: AppendBufferAsString(value, toStr); break; - case GPBTypeMessage: + case GPBDataTypeMessage: [toStr appendString:@"{\n"]; NSString *subIndent = [lineIndent stringByAppendingString:@" "]; AppendTextFormatForMessage(value, toStr, subIndent); @@ -1133,7 +1158,7 @@ static void AppendTextFormatForMapMessageField( isFirst = NO; // Key always is a NSString. - if (keyType == GPBTypeString) { + if (keyDataType == GPBDataTypeString) { [toStr appendString:keyLine]; AppendStringEscaped(keyObj, toStr); [toStr appendString:@"\n"]; @@ -1142,23 +1167,23 @@ static void AppendTextFormatForMapMessageField( } [toStr appendString:valueLine]; - switch (valueType) { - case GPBTypeString: + switch (valueDataType) { + case GPBDataTypeString: AppendStringEscaped(valueObj, toStr); break; - case GPBTypeData: + case GPBDataTypeBytes: AppendBufferAsString(valueObj, toStr); break; - case GPBTypeMessage: + case GPBDataTypeMessage: [toStr appendString:@"{\n"]; NSString *subIndent = [lineIndent stringByAppendingString:@" "]; AppendTextFormatForMessage(valueObj, toStr, subIndent); [toStr appendFormat:@"%@ }", lineIndent]; break; - case GPBTypeEnum: { + case GPBDataTypeEnum: { int32_t enumValue = [valueObj intValue]; NSString *valueStr = nil; GPBEnumDescriptor *descriptor = field.enumDescriptor; @@ -1174,7 +1199,7 @@ static void AppendTextFormatForMapMessageField( } default: - NSCAssert(valueType != GPBTypeGroup, @"Can't happen"); + NSCAssert(valueDataType != GPBDataTypeGroup, @"Can't happen"); // Everything else is a NSString. [toStr appendString:valueObj]; break; @@ -1245,8 +1270,8 @@ static void AppendTextFormatForMessageField(GPBMessage *message, id array = arrayOrMap; const BOOL isRepeated = (array != nil); - GPBType fieldDataType = GPBGetFieldType(field); - BOOL isMessageField = GPBTypeIsMessage(fieldDataType); + GPBDataType fieldDataType = GPBGetFieldDataType(field); + BOOL isMessageField = GPBDataTypeIsMessage(fieldDataType); for (NSUInteger j = 0; j < count; ++j) { // Start the line. [toStr appendFormat:@"%@%@%s ", lineIndent, fieldName, @@ -1254,12 +1279,12 @@ static void AppendTextFormatForMessageField(GPBMessage *message, // 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; \ +#define FIELD_CASE(GPBDATATYPE, CTYPE, REAL_TYPE, ...) \ + case GPBDataType##GPBDATATYPE: { \ + CTYPE v = (isRepeated ? [(GPB##REAL_TYPE##Array *)array valueAtIndex:j] \ + : GPBGetMessage##REAL_TYPE##Field(message, field)); \ + [toStr appendFormat:__VA_ARGS__, v]; \ + break; \ } FIELD_CASE(Int32, int32_t, Int32, @"%d") @@ -1277,9 +1302,9 @@ static void AppendTextFormatForMessageField(GPBMessage *message, #undef FIELD_CASE - case GPBTypeEnum: { + case GPBDataTypeEnum: { int32_t v = (isRepeated ? [(GPBEnumArray *)array rawValueAtIndex:j] - : GPBGetInt32IvarWithField(message, field)); + : GPBGetMessageInt32Field(message, field)); NSString *valueStr = nil; GPBEnumDescriptor *descriptor = field.enumDescriptor; if (descriptor) { @@ -1293,29 +1318,29 @@ static void AppendTextFormatForMessageField(GPBMessage *message, break; } - case GPBTypeBool: { + case GPBDataTypeBool: { BOOL v = (isRepeated ? [(GPBBoolArray *)array valueAtIndex:j] - : GPBGetBoolIvarWithField(message, field)); + : GPBGetMessageBoolField(message, field)); [toStr appendString:(v ? @"true" : @"false")]; break; } - case GPBTypeString: { + case GPBDataTypeString: { NSString *v = (isRepeated ? [(NSArray *)array objectAtIndex:j] - : GPBGetStringIvarWithField(message, field)); + : GPBGetMessageStringField(message, field)); AppendStringEscaped(v, toStr); break; } - case GPBTypeData: { + case GPBDataTypeBytes: { NSData *v = (isRepeated ? [(NSArray *)array objectAtIndex:j] - : GPBGetDataIvarWithField(message, field)); + : GPBGetMessageBytesField(message, field)); AppendBufferAsString(v, toStr); break; } - case GPBTypeGroup: - case GPBTypeMessage: { + case GPBDataTypeGroup: + case GPBDataTypeMessage: { GPBMessage *v = (isRepeated ? [(NSArray *)array objectAtIndex:j] : GPBGetObjectIvarWithField(message, field)); @@ -1342,7 +1367,7 @@ static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, NSString *lineIndent) { uint32_t start = range.start; uint32_t end = range.end; - for (GPBExtensionField *extension in activeExtensions) { + for (GPBExtensionDescriptor *extension in activeExtensions) { uint32_t fieldNumber = extension.fieldNumber; if (fieldNumber < start) { // Not there yet. @@ -1354,8 +1379,7 @@ static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, } id rawExtValue = [message getExtension:extension]; - GPBExtensionDescriptor *extDescriptor = [extension descriptor]; - BOOL isRepeated = extDescriptor.isRepeated; + BOOL isRepeated = extension.isRepeated; NSUInteger numValues = 1; NSString *lineEnding = @""; @@ -1363,28 +1387,28 @@ static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, numValues = [(NSArray *)rawExtValue count]; } - NSString *singletonName = extension.descriptor.singletonName; + NSString *singletonName = extension.singletonName; if (numValues == 1) { lineEnding = [NSString stringWithFormat:@" # [%@]", singletonName]; } else { [toStr appendFormat:@"%@# [%@]\n", lineIndent, singletonName]; } - GPBType extType = extDescriptor.type; + GPBDataType extDataType = extension.dataType; 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) ? "" : ":")]; + (GPBDataTypeIsMessage(extDataType) ? "" : ":")]; // The value. - switch (extType) { -#define FIELD_CASE(GPBTYPE, CTYPE, NUMSELECTOR, ...) \ - case GPBType##GPBTYPE: { \ - CTYPE v = [(NSNumber *)curValue NUMSELECTOR]; \ - [toStr appendFormat:__VA_ARGS__, v]; \ - break; \ + switch (extDataType) { +#define FIELD_CASE(GPBDATATYPE, CTYPE, NUMSELECTOR, ...) \ + case GPBDataType##GPBDATATYPE: { \ + CTYPE v = [(NSNumber *)curValue NUMSELECTOR]; \ + [toStr appendFormat:__VA_ARGS__, v]; \ + break; \ } FIELD_CASE(Int32, int32_t, intValue, @"%d") @@ -1408,21 +1432,21 @@ static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, #undef FIELD_CASE - case GPBTypeBool: + case GPBDataTypeBool: [toStr appendString:([(NSNumber *)curValue boolValue] ? @"true" : @"false")]; break; - case GPBTypeString: + case GPBDataTypeString: AppendStringEscaped(curValue, toStr); break; - case GPBTypeData: + case GPBDataTypeBytes: AppendBufferAsString((NSData *)curValue, toStr); break; - case GPBTypeGroup: - case GPBTypeMessage: { + case GPBDataTypeGroup: + case GPBDataTypeMessage: { [toStr appendFormat:@"{%@\n", lineEnding]; NSString *subIndent = [lineIndent stringByAppendingString:@" "]; AppendTextFormatForMessage(curValue, toStr, subIndent); @@ -1431,7 +1455,7 @@ static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, break; } - } // switch(extType) + } // switch(extDataType) } // for(numValues) @@ -1473,7 +1497,7 @@ static void AppendTextFormatForMessage(GPBMessage *message, } NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *lineIndent) { - if (message == nil) return nil; + if (message == nil) return @""; if (lineIndent == nil) lineIndent = @""; NSMutableString *buildString = [NSMutableString string]; @@ -1483,11 +1507,11 @@ NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *lineIndent) { NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet, NSString *lineIndent) { - if (unknownSet == nil) return nil; + if (unknownSet == nil) return @""; if (lineIndent == nil) lineIndent = @""; NSMutableString *result = [NSMutableString string]; - for (GPBField *field in [unknownSet sortedFields]) { + for (GPBUnknownField *field in [unknownSet sortedFields]) { int32_t fieldNumber = [field number]; #define PRINT_LOOP(PROPNAME, CTYPE, FORMAT) \ @@ -1527,13 +1551,13 @@ NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet, // 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) { +GPB_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) { +static int32_t ReadRawVarint32FromData(const uint8_t **data) { int8_t tmp = ReadRawByteFromData(data); if (tmp >= 0) { return tmp; diff --git a/objectivec/GPBUtilities_PackagePrivate.h b/objectivec/GPBUtilities_PackagePrivate.h index 1481d071..cac551f6 100644 --- a/objectivec/GPBUtilities_PackagePrivate.h +++ b/objectivec/GPBUtilities_PackagePrivate.h @@ -48,6 +48,15 @@ CF_EXTERN_C_BEGIN +// These two are used to inject a runtime check for version mismatch into the +// generated sources to make sure they are linked with a supporting runtime. +void GPBCheckRuntimeVersionInternal(int32_t version); +GPB_INLINE void GPBDebugCheckRuntimeVersion() { +#if DEBUG + GPBCheckRuntimeVersionInternal(GOOGLE_PROTOBUF_OBJC_GEN_VERSION); +#endif +} + // Conversion functions for de/serializing floating point types. GPB_INLINE int64_t GPBConvertDoubleToInt64(double v) { @@ -116,40 +125,38 @@ GPB_INLINE uint64_t GPBEncodeZigZag64(int64_t n) { return (n << 1) ^ (n >> 63); } -GPB_INLINE BOOL GPBTypeIsObject(GPBType type) { +GPB_INLINE BOOL GPBDataTypeIsObject(GPBDataType type) { switch (type) { - case GPBTypeData: - case GPBTypeString: - case GPBTypeMessage: - case GPBTypeGroup: + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: return YES; default: return NO; } } -GPB_INLINE BOOL GPBTypeIsMessage(GPBType type) { +GPB_INLINE BOOL GPBDataTypeIsMessage(GPBDataType type) { switch (type) { - case GPBTypeMessage: - case GPBTypeGroup: + case GPBDataTypeMessage: + case GPBDataTypeGroup: 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 GPBFieldDataTypeIsMessage(GPBFieldDescriptor *field) { + return GPBDataTypeIsMessage(field->description_->dataType); } -GPB_INLINE BOOL GPBFieldTypeIsObject(GPBFieldDescriptor *field) { - return GPBTypeIsObject(field->description_->type); +GPB_INLINE BOOL GPBFieldDataTypeIsObject(GPBFieldDescriptor *field) { + return GPBDataTypeIsObject(field->description_->dataType); } GPB_INLINE BOOL GPBExtensionIsMessage(GPBExtensionDescriptor *ext) { - return GPBTypeIsMessage(ext->description_->type); + return GPBDataTypeIsMessage(ext->description_->dataType); } // The field is an array/map or it has an object value. @@ -158,7 +165,7 @@ GPB_INLINE BOOL GPBFieldStoresObject(GPBFieldDescriptor *field) { if ((desc->flags & (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0) { return YES; } - return GPBTypeIsObject(desc->type); + return GPBDataTypeIsObject(desc->dataType); } BOOL GPBGetHasIvar(GPBMessage *self, int32_t index, uint32_t fieldNumber); @@ -272,109 +279,6 @@ void GPBSetAutocreatedRetainedObjectIvarWithField( 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. @@ -410,7 +314,7 @@ 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(NSData *, Bytes) GPB_MESSAGE_SIGNATURE_ENTRY(NSString *, String) GPB_MESSAGE_SIGNATURE_ENTRY(GPBMessage *, Message) GPB_MESSAGE_SIGNATURE_ENTRY(GPBMessage *, Group) @@ -419,6 +323,7 @@ GPB_MESSAGE_SIGNATURE_ENTRY(int32_t, Enum) #undef GPB_MESSAGE_SIGNATURE_ENTRY - (id)getArray; +- (NSUInteger)getArrayCount; - (void)setArray:(NSArray *)array; + (id)getClassValue; @end diff --git a/objectivec/GPBWellKnownTypes.h b/objectivec/GPBWellKnownTypes.h index 321cdc3e..c98594a2 100644 --- a/objectivec/GPBWellKnownTypes.h +++ b/objectivec/GPBWellKnownTypes.h @@ -33,6 +33,8 @@ #import "google/protobuf/Timestamp.pbobjc.h" #import "google/protobuf/Duration.pbobjc.h" +NS_ASSUME_NONNULL_BEGIN + // Extension to GPBTimestamp to work with standard Foundation time/date types. @interface GPBTimestamp (GBPWellKnownTypes) @property(nonatomic, readwrite, strong) NSDate *date; @@ -46,3 +48,5 @@ @property(nonatomic, readwrite) NSTimeInterval timeIntervalSince1970; - (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970; @end + +NS_ASSUME_NONNULL_END diff --git a/objectivec/GPBWireFormat.h b/objectivec/GPBWireFormat.h index 55f2edfc..29cf2f0b 100644 --- a/objectivec/GPBWireFormat.h +++ b/objectivec/GPBWireFormat.h @@ -28,10 +28,12 @@ // (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" +#import "GPBRuntimeTypes.h" CF_EXTERN_C_BEGIN +NS_ASSUME_NONNULL_BEGIN + typedef enum { GPBWireFormatVarint = 0, GPBWireFormatFixed64 = 1, @@ -52,7 +54,7 @@ uint32_t GPBWireFormatMakeTag(uint32_t fieldNumber, GPBWireFormat wireType) GPBWireFormat GPBWireFormatGetTagWireType(uint32_t tag) __attribute__((const)); uint32_t GPBWireFormatGetTagFieldNumber(uint32_t tag) __attribute__((const)); -GPBWireFormat GPBWireFormatForType(GPBType type, BOOL isPacked) +GPBWireFormat GPBWireFormatForType(GPBDataType dataType, BOOL isPacked) __attribute__((const)); #define GPBWireFormatMessageSetItemTag \ @@ -65,4 +67,6 @@ GPBWireFormat GPBWireFormatForType(GPBType type, BOOL isPacked) (GPBWireFormatMakeTag(GPBWireFormatMessageSetMessage, \ GPBWireFormatLengthDelimited)) +NS_ASSUME_NONNULL_END + CF_EXTERN_C_END diff --git a/objectivec/GPBWireFormat.m b/objectivec/GPBWireFormat.m index 7435221f..193235d6 100644 --- a/objectivec/GPBWireFormat.m +++ b/objectivec/GPBWireFormat.m @@ -49,30 +49,30 @@ uint32_t GPBWireFormatGetTagFieldNumber(uint32_t tag) { return GPBLogicalRightShift32(tag, GPBWireFormatTagTypeBits); } -GPBWireFormat GPBWireFormatForType(GPBType type, BOOL isPacked) { +GPBWireFormat GPBWireFormatForType(GPBDataType 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 + static const GPBWireFormat format[GPBDataType_Count] = { + GPBWireFormatVarint, // GPBDataTypeBool + GPBWireFormatFixed32, // GPBDataTypeFixed32 + GPBWireFormatFixed32, // GPBDataTypeSFixed32 + GPBWireFormatFixed32, // GPBDataTypeFloat + GPBWireFormatFixed64, // GPBDataTypeFixed64 + GPBWireFormatFixed64, // GPBDataTypeSFixed64 + GPBWireFormatFixed64, // GPBDataTypeDouble + GPBWireFormatVarint, // GPBDataTypeInt32 + GPBWireFormatVarint, // GPBDataTypeInt64 + GPBWireFormatVarint, // GPBDataTypeSInt32 + GPBWireFormatVarint, // GPBDataTypeSInt64 + GPBWireFormatVarint, // GPBDataTypeUInt32 + GPBWireFormatVarint, // GPBDataTypeUInt64 + GPBWireFormatLengthDelimited, // GPBDataTypeBytes + GPBWireFormatLengthDelimited, // GPBDataTypeString + GPBWireFormatLengthDelimited, // GPBDataTypeMessage + GPBWireFormatStartGroup, // GPBDataTypeGroup + GPBWireFormatVarint // GPBDataTypeEnum }; return format[type]; } diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj index f18ba2f8..b0a0712e 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj @@ -6,20 +6,6 @@ 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 */; }; @@ -27,7 +13,7 @@ 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 */; }; + 7461B54C0F94FB4E00A0C422 /* GPBUnknownField.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4AF0F94F99000A0C422 /* GPBUnknownField.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 */; }; @@ -51,7 +37,6 @@ 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 */; }; @@ -71,8 +56,24 @@ 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 */; }; + F45C69CC16DFD08D0081955B /* GPBExtensionInternals.m in Sources */ = {isa = PBXBuildFile; fileRef = F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */; }; F45E57C71AE6DC6A000B7D99 /* text_format_map_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F45E57C61AE6DC6A000B7D99 /* text_format_map_unittest_data.txt */; }; + F4E675971B21D0000054530B /* Any.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675871B21D0000054530B /* Any.pbobjc.m */; }; + F4E675991B21D0000054530B /* Api.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675891B21D0000054530B /* Api.pbobjc.m */; }; + F4E6759B1B21D0000054530B /* Empty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758B1B21D0000054530B /* Empty.pbobjc.m */; }; + F4E6759D1B21D0000054530B /* FieldMask.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758D1B21D0000054530B /* FieldMask.pbobjc.m */; }; + F4E6759F1B21D0000054530B /* SourceContext.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758F1B21D0000054530B /* SourceContext.pbobjc.m */; }; + F4E675A11B21D0000054530B /* Struct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675911B21D0000054530B /* Struct.pbobjc.m */; }; + F4E675A31B21D0000054530B /* Type.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675931B21D0000054530B /* Type.pbobjc.m */; }; + F4E675A51B21D0000054530B /* Wrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675951B21D0000054530B /* Wrappers.pbobjc.m */; }; + F4E675AE1B21D0A70054530B /* Any.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675871B21D0000054530B /* Any.pbobjc.m */; }; + F4E675AF1B21D0A70054530B /* Api.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675891B21D0000054530B /* Api.pbobjc.m */; }; + F4E675B01B21D0A70054530B /* Empty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758B1B21D0000054530B /* Empty.pbobjc.m */; }; + F4E675B11B21D0A70054530B /* FieldMask.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758D1B21D0000054530B /* FieldMask.pbobjc.m */; }; + F4E675B21B21D0A70054530B /* SourceContext.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758F1B21D0000054530B /* SourceContext.pbobjc.m */; }; + F4E675B31B21D0A70054530B /* Struct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675911B21D0000054530B /* Struct.pbobjc.m */; }; + F4E675B41B21D0A70054530B /* Type.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675931B21D0000054530B /* Type.pbobjc.m */; }; + F4E675B51B21D0A70054530B /* Wrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675951B21D0000054530B /* Wrappers.pbobjc.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -83,12 +84,12 @@ remoteGlobalIDString = 7461B52D0F94FAF800A0C422; remoteInfo = ProtocolBuffers; }; - 8BD3982014BE59EB0081D629 /* PBXContainerItemProxy */ = { + F45BBC181B0CE3D7002D064D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; proxyType = 1; - remoteGlobalIDString = 8BD3981414BE4AE70081D629; - remoteInfo = Compile_Protos; + remoteGlobalIDString = F45BBC141B0CE3C6002D064D; + remoteInfo = "Compile Unittest Protos"; }; /* End PBXContainerItemProxy section */ @@ -106,8 +107,8 @@ 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>"; }; + 7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownField.h; sourceTree = "<group>"; }; + 7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownField.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>"; }; @@ -126,10 +127,7 @@ 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; }; @@ -162,12 +160,11 @@ 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>"; }; + 8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.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>"; }; @@ -192,16 +189,39 @@ 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>"; }; + F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionInternals.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>"; }; + F4B6B8AF1A9CC98000892426 /* GPBUnknownField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownField_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>"; }; + F4B6B8B61A9CD1DE00892426 /* GPBExtensionInternals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionInternals.h; sourceTree = "<group>"; }; F4B6B8B81A9CD1DE00892426 /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRootObject_PackagePrivate.h; sourceTree = "<group>"; }; - F4B6B8B91A9D338B00892426 /* unittest_name_mangling.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_name_mangling.proto; sourceTree = "<group>"; }; + F4CF31701B162ED800BD9B06 /* unittest_objc_startup.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc_startup.proto; sourceTree = "<group>"; }; + F4E675861B21D0000054530B /* Any.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Any.pbobjc.h; path = google/protobuf/Any.pbobjc.h; sourceTree = "<group>"; }; + F4E675871B21D0000054530B /* Any.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Any.pbobjc.m; path = google/protobuf/Any.pbobjc.m; sourceTree = "<group>"; }; + F4E675881B21D0000054530B /* Api.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Api.pbobjc.h; path = google/protobuf/Api.pbobjc.h; sourceTree = "<group>"; }; + F4E675891B21D0000054530B /* Api.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Api.pbobjc.m; path = google/protobuf/Api.pbobjc.m; sourceTree = "<group>"; }; + F4E6758A1B21D0000054530B /* Empty.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Empty.pbobjc.h; path = google/protobuf/Empty.pbobjc.h; sourceTree = "<group>"; }; + F4E6758B1B21D0000054530B /* Empty.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Empty.pbobjc.m; path = google/protobuf/Empty.pbobjc.m; sourceTree = "<group>"; }; + F4E6758C1B21D0000054530B /* FieldMask.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FieldMask.pbobjc.h; path = google/protobuf/FieldMask.pbobjc.h; sourceTree = "<group>"; }; + F4E6758D1B21D0000054530B /* FieldMask.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FieldMask.pbobjc.m; path = google/protobuf/FieldMask.pbobjc.m; sourceTree = "<group>"; }; + F4E6758E1B21D0000054530B /* SourceContext.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SourceContext.pbobjc.h; path = google/protobuf/SourceContext.pbobjc.h; sourceTree = "<group>"; }; + F4E6758F1B21D0000054530B /* SourceContext.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SourceContext.pbobjc.m; path = google/protobuf/SourceContext.pbobjc.m; sourceTree = "<group>"; }; + F4E675901B21D0000054530B /* Struct.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Struct.pbobjc.h; path = google/protobuf/Struct.pbobjc.h; sourceTree = "<group>"; }; + F4E675911B21D0000054530B /* Struct.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Struct.pbobjc.m; path = google/protobuf/Struct.pbobjc.m; sourceTree = "<group>"; }; + F4E675921B21D0000054530B /* Type.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Type.pbobjc.h; path = google/protobuf/Type.pbobjc.h; sourceTree = "<group>"; }; + F4E675931B21D0000054530B /* Type.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Type.pbobjc.m; path = google/protobuf/Type.pbobjc.m; sourceTree = "<group>"; }; + F4E675941B21D0000054530B /* Wrappers.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Wrappers.pbobjc.h; path = google/protobuf/Wrappers.pbobjc.h; sourceTree = "<group>"; }; + F4E675951B21D0000054530B /* Wrappers.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Wrappers.pbobjc.m; path = google/protobuf/Wrappers.pbobjc.m; sourceTree = "<group>"; }; + F4E675A61B21D05C0054530B /* any.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = any.proto; path = ../src/google/protobuf/any.proto; sourceTree = "<group>"; }; + F4E675A71B21D05C0054530B /* api.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = api.proto; path = ../src/google/protobuf/api.proto; sourceTree = "<group>"; }; + F4E675A81B21D05C0054530B /* empty.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = empty.proto; path = ../src/google/protobuf/empty.proto; sourceTree = "<group>"; }; + F4E675A91B21D05C0054530B /* field_mask.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = field_mask.proto; path = ../src/google/protobuf/field_mask.proto; sourceTree = "<group>"; }; + F4E675AA1B21D05C0054530B /* source_context.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = source_context.proto; path = ../src/google/protobuf/source_context.proto; sourceTree = "<group>"; }; + F4E675AB1B21D05C0054530B /* struct.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = struct.proto; path = ../src/google/protobuf/struct.proto; sourceTree = "<group>"; }; + F4E675AC1B21D05C0054530B /* type.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = type.proto; path = ../src/google/protobuf/type.proto; sourceTree = "<group>"; }; + F4E675AD1B21D05C0054530B /* wrappers.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = wrappers.proto; path = ../src/google/protobuf/wrappers.proto; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -273,15 +293,39 @@ 29B97315FDCFA39411CA2CEA /* Generated */ = { isa = PBXGroup; children = ( - 8B42494B1A92A16600BC1EC6 /* descriptor.proto */, - 8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */, + F4E675861B21D0000054530B /* Any.pbobjc.h */, + F4E675871B21D0000054530B /* Any.pbobjc.m */, + F4E675A61B21D05C0054530B /* any.proto */, + F4E675881B21D0000054530B /* Api.pbobjc.h */, + F4E675891B21D0000054530B /* Api.pbobjc.m */, + F4E675A71B21D05C0054530B /* api.proto */, 8B54585814DCC34E003D7338 /* Descriptor.pbobjc.h */, - 8B42494C1A92A16600BC1EC6 /* duration.proto */, + 8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */, + 8B42494B1A92A16600BC1EC6 /* descriptor.proto */, 8B4248D31A92826400BC1EC6 /* Duration.pbobjc.h */, 8B4248D41A92826400BC1EC6 /* Duration.pbobjc.m */, - 8B42494D1A92A16600BC1EC6 /* timestamp.proto */, + 8B42494C1A92A16600BC1EC6 /* duration.proto */, + F4E6758A1B21D0000054530B /* Empty.pbobjc.h */, + F4E6758B1B21D0000054530B /* Empty.pbobjc.m */, + F4E675A81B21D05C0054530B /* empty.proto */, + F4E675A91B21D05C0054530B /* field_mask.proto */, + F4E6758C1B21D0000054530B /* FieldMask.pbobjc.h */, + F4E6758D1B21D0000054530B /* FieldMask.pbobjc.m */, + F4E675AA1B21D05C0054530B /* source_context.proto */, + F4E6758E1B21D0000054530B /* SourceContext.pbobjc.h */, + F4E6758F1B21D0000054530B /* SourceContext.pbobjc.m */, + F4E675901B21D0000054530B /* Struct.pbobjc.h */, + F4E675911B21D0000054530B /* Struct.pbobjc.m */, + F4E675AB1B21D05C0054530B /* struct.proto */, 8B4248D51A92826400BC1EC6 /* Timestamp.pbobjc.h */, 8B4248D61A92826400BC1EC6 /* Timestamp.pbobjc.m */, + 8B42494D1A92A16600BC1EC6 /* timestamp.proto */, + F4E675921B21D0000054530B /* Type.pbobjc.h */, + F4E675931B21D0000054530B /* Type.pbobjc.m */, + F4E675AC1B21D05C0054530B /* type.proto */, + F4E675941B21D0000054530B /* Wrappers.pbobjc.h */, + F4E675951B21D0000054530B /* Wrappers.pbobjc.m */, + F4E675AD1B21D05C0054530B /* wrappers.proto */, ); name = Generated; sourceTree = "<group>"; @@ -297,9 +341,8 @@ 7461B3C50F94F84100A0C422 /* Extensions */ = { isa = PBXGroup; children = ( - F4B6B8B61A9CD1DE00892426 /* GPBExtensionField_PackagePrivate.h */, - 748F0CAF0FD70602000858A9 /* GPBExtensionField.h */, - F45C69CB16DFD08D0081955B /* GPBExtensionField.m */, + F4B6B8B61A9CD1DE00892426 /* GPBExtensionInternals.h */, + F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */, 7461B4A80F94F99000A0C422 /* GPBExtensionRegistry.h */, 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */, F4B6B8B81A9CD1DE00892426 /* GPBRootObject_PackagePrivate.h */, @@ -312,9 +355,9 @@ 7461B4850F94F96600A0C422 /* Fields */ = { isa = PBXGroup; children = ( - F4B6B8AF1A9CC98000892426 /* GPBField_PackagePrivate.h */, - 7461B4AE0F94F99000A0C422 /* GPBField.h */, - 7461B4AF0F94F99000A0C422 /* GPBField.m */, + F4B6B8AF1A9CC98000892426 /* GPBUnknownField_PackagePrivate.h */, + 7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */, + 7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */, F4B6B8B21A9CCBDA00892426 /* GPBUnknownFieldSet_PackagePrivate.h */, 7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */, 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */, @@ -353,8 +396,6 @@ isa = PBXGroup; children = ( 8B4248B81A8C254000BC1EC6 /* protobuf */, - 8B20A9A816F1BBFA00BE3EAD /* Filter1.txt */, - F44B25D81A729803005CCF68 /* Filter2.txt */, 8B210CCD159383D60032D72D /* golden_message */, 8B210CCF159386920032D72D /* golden_packed_fields_message */, 8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */, @@ -370,7 +411,6 @@ 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 */, @@ -392,13 +432,12 @@ 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 */, + F4CF31701B162ED800BD9B06 /* unittest_objc_startup.proto */, 8B7E6A7D14893DBC00F8884A /* unittest_optimize_for.proto */, F4487C781AADFB3100531423 /* unittest_runtime_proto2.proto */, F4487C791AADFB3200531423 /* unittest_runtime_proto3.proto */, @@ -419,7 +458,7 @@ F43725911AC9832D004DCAFB /* GPBDictionary_PackagePrivate.h */, F4353D201ABB1537005A6198 /* GPBDictionary.h */, F4353D211ABB1537005A6198 /* GPBDictionary.m */, - 8BEB5AE01498033E0078BF9D /* GPBTypes.h */, + 8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */, F4487C7C1AAE06AC00531423 /* GPBUtilities_PackagePrivate.h */, 7461B4E50F94F99000A0C422 /* GPBUtilities.h */, 7461B4E60F94F99000A0C422 /* GPBUtilities.m */, @@ -448,6 +487,22 @@ }; /* End PBXHeadersBuildPhase section */ +/* Begin PBXLegacyTarget section */ + F45BBC141B0CE3C6002D064D /* Compile Unittest Protos */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "$(ACTION)"; + buildConfigurationList = F45BBC171B0CE3C6002D064D /* Build configuration list for PBXLegacyTarget "Compile Unittest Protos" */; + buildPhases = ( + ); + buildToolPath = DevTools/compile_testing_protos.sh; + dependencies = ( + ); + name = "Compile Unittest Protos"; + passBuildSettingsInEnvironment = 1; + productName = "Compile Unittest Protos"; + }; +/* End PBXLegacyTarget section */ + /* Begin PBXNativeTarget section */ 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */ = { isa = PBXNativeTarget; @@ -479,7 +534,7 @@ ); dependencies = ( 8BBEA4BD147C729A00C4ADB7 /* PBXTargetDependency */, - 8BD3982114BE59EB0081D629 /* PBXTargetDependency */, + F45BBC191B0CE3D7002D064D /* PBXTargetDependency */, ); name = UnitTests; productName = UnitTests; @@ -510,11 +565,14 @@ isa = PBXProject; attributes = { LastTestingUpgradeCheck = 0600; - LastUpgradeCheck = 0620; + LastUpgradeCheck = 0630; TargetAttributes = { 8BBEA4A5147C727100C4ADB7 = { TestTargetID = 8B9A5EA41831993600A9D33B; }; + F45BBC141B0CE3C6002D064D = { + CreatedOnToolsVersion = 6.3.2; + }; }; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProtocolBuffers_OSX" */; @@ -530,8 +588,8 @@ targets = ( 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */, 8BBEA4A5147C727100C4ADB7 /* UnitTests */, - 8BD3981414BE4AE70081D629 /* Compile_Protos */, F4487C381A9F8E0200531423 /* TestSingleSourceBuild */, + F45BBC141B0CE3C6002D064D /* Compile Unittest Protos */, ); }; /* End PBXProject section */ @@ -551,51 +609,6 @@ /* 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\n# Use the filter\nexport GPB_OBJC_CLASS_WHITELIST_PATHS=\"${SRCROOT}/Tests/Filter1.txt;${SRCROOT}/Tests/Filter2.txt\"\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; @@ -620,19 +633,27 @@ files = ( 2CFB390415C718CE00CBF84D /* Descriptor.pbobjc.m in Sources */, 7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */, + F4E6759B1B21D0000054530B /* Empty.pbobjc.m in Sources */, 7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */, F401DC2D1A8D444600FCC765 /* GPBArray.m in Sources */, 7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */, - 7461B54C0F94FB4E00A0C422 /* GPBField.m in Sources */, + F4E6759D1B21D0000054530B /* FieldMask.pbobjc.m in Sources */, + 7461B54C0F94FB4E00A0C422 /* GPBUnknownField.m in Sources */, 7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */, 7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */, 7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */, 7461B5640F94FB4E00A0C422 /* GPBWireFormat.m in Sources */, + F4E675991B21D0000054530B /* Api.pbobjc.m in Sources */, + F4E6759F1B21D0000054530B /* SourceContext.pbobjc.m in Sources */, F4353D231ABB1537005A6198 /* GPBDictionary.m in Sources */, 8B79657B14992E3F002FFBFC /* GPBRootObject.m in Sources */, 8B96157414C8C38C00A2AC0B /* GPBDescriptor.m in Sources */, - F45C69CC16DFD08D0081955B /* GPBExtensionField.m in Sources */, + F4E675971B21D0000054530B /* Any.pbobjc.m in Sources */, + F45C69CC16DFD08D0081955B /* GPBExtensionInternals.m in Sources */, 8B4248D21A927E1500BC1EC6 /* GPBWellKnownTypes.m in Sources */, + F4E675A31B21D0000054530B /* Type.pbobjc.m in Sources */, + F4E675A11B21D0000054530B /* Struct.pbobjc.m in Sources */, + F4E675A51B21D0000054530B /* Wrappers.pbobjc.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -645,12 +666,18 @@ F4353D361AC06F10005A6198 /* GPBDictionaryTests+Int64.m in Sources */, F4353D391AC06F10005A6198 /* GPBDictionaryTests+UInt64.m in Sources */, 8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */, + F4E675B21B21D0A70054530B /* SourceContext.pbobjc.m in Sources */, 8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */, F4487C7F1AAF62CD00531423 /* GPBMessageTests+Serialization.m in Sources */, 8B4248DC1A92933A00BC1EC6 /* GPBWellKnownTypesTest.m in Sources */, + F4E675B01B21D0A70054530B /* Empty.pbobjc.m in Sources */, + F4E675B41B21D0A70054530B /* Type.pbobjc.m in Sources */, F4353D1D1AB8822D005A6198 /* GPBDescriptorTests.m in Sources */, + F4E675B51B21D0A70054530B /* Wrappers.pbobjc.m in Sources */, + F4E675AE1B21D0A70054530B /* Any.pbobjc.m in Sources */, 8B4248BB1A8C256A00BC1EC6 /* GPBSwiftTests.swift in Sources */, 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */, + F4E675B31B21D0A70054530B /* Struct.pbobjc.m in Sources */, F4487C751AADF7F500531423 /* GPBMessageTests+Runtime.m in Sources */, F4353D351AC06F10005A6198 /* GPBDictionaryTests+Int32.m in Sources */, 8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */, @@ -665,9 +692,10 @@ 8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */, 8B79657D14992E3F002FFBFC /* GPBRootObject.m in Sources */, 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */, + F4E675B11B21D0A70054530B /* FieldMask.pbobjc.m in Sources */, 8B96157514CA019D00A2AC0B /* Descriptor.pbobjc.m in Sources */, - 8BCC29BF16FD09A000F29F4A /* GPBFilteredMessageTests.m in Sources */, 8B8B615D17DF7056002EE618 /* GPBARCUnittestProtos.m in Sources */, + F4E675AF1B21D0A70054530B /* Api.pbobjc.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -687,10 +715,10 @@ target = 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */; targetProxy = 8BBEA4BC147C729A00C4ADB7 /* PBXContainerItemProxy */; }; - 8BD3982114BE59EB0081D629 /* PBXTargetDependency */ = { + F45BBC191B0CE3D7002D064D /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 8BD3981414BE4AE70081D629 /* Compile_Protos */; - targetProxy = 8BD3982014BE59EB0081D629 /* PBXContainerItemProxy */; + target = F45BBC141B0CE3C6002D064D /* Compile Unittest Protos */; + targetProxy = F45BBC181B0CE3D7002D064D /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ @@ -746,20 +774,6 @@ }; 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 = { @@ -864,6 +878,18 @@ }; name = Release; }; + F45BBC151B0CE3C6002D064D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + F45BBC161B0CE3C6002D064D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -885,15 +911,6 @@ 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 = ( @@ -912,6 +929,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + F45BBC171B0CE3C6002D064D /* Build configuration list for PBXLegacyTarget "Compile Unittest Protos" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F45BBC151B0CE3C6002D064D /* Debug */, + F45BBC161B0CE3C6002D064D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme index 7083f5e3..3b3eeb12 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "0620" + LastUpgradeVersion = "0630" version = "1.3"> <BuildAction parallelizeBuildables = "YES" @@ -39,9 +39,6 @@ </BuildableReference> <SkippedTests> <Test - Identifier = "ArrayTests"> - </Test> - <Test Identifier = "CodedInputStreamTests"> </Test> <Test @@ -51,16 +48,223 @@ Identifier = "ConcurrencyTests"> </Test> <Test - Identifier = "FilteredMessageTests"> + Identifier = "DescriptorTests"> + </Test> + <Test + Identifier = "GPBBoolArrayTests"> + </Test> + <Test + Identifier = "GPBBoolBoolDictionaryTests"> + </Test> + <Test + Identifier = "GPBBoolDoubleDictionaryTests"> + </Test> + <Test + Identifier = "GPBBoolFloatDictionaryTests"> + </Test> + <Test + Identifier = "GPBBoolInt32DictionaryTests"> + </Test> + <Test + Identifier = "GPBBoolInt64DictionaryTests"> + </Test> + <Test + Identifier = "GPBBoolObjectDictionaryTests"> + </Test> + <Test + Identifier = "GPBBoolUInt32DictionaryTests"> + </Test> + <Test + Identifier = "GPBBoolUInt64DictionaryTests"> + </Test> + <Test + Identifier = "GPBBridgeTests"> + </Test> + <Test + Identifier = "GPBDoubleArrayTests"> + </Test> + <Test + Identifier = "GPBEnumArrayCustomTests"> + </Test> + <Test + Identifier = "GPBEnumArrayTests"> + </Test> + <Test + Identifier = "GPBFloatArrayTests"> + </Test> + <Test + Identifier = "GPBInt32ArrayTests"> + </Test> + <Test + Identifier = "GPBInt32BoolDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt32DoubleDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt32EnumDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt32EnumDictionaryUnknownEnumTests"> + </Test> + <Test + Identifier = "GPBInt32FloatDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt32Int32DictionaryTests"> + </Test> + <Test + Identifier = "GPBInt32Int64DictionaryTests"> + </Test> + <Test + Identifier = "GPBInt32ObjectDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt32UInt32DictionaryTests"> + </Test> + <Test + Identifier = "GPBInt32UInt64DictionaryTests"> + </Test> + <Test + Identifier = "GPBInt64ArrayTests"> + </Test> + <Test + Identifier = "GPBInt64BoolDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt64DoubleDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt64EnumDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt64EnumDictionaryUnknownEnumTests"> + </Test> + <Test + Identifier = "GPBInt64FloatDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt64Int32DictionaryTests"> + </Test> + <Test + Identifier = "GPBInt64Int64DictionaryTests"> + </Test> + <Test + Identifier = "GPBInt64ObjectDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt64UInt32DictionaryTests"> + </Test> + <Test + Identifier = "GPBInt64UInt64DictionaryTests"> + </Test> + <Test + Identifier = "GPBStringBoolDictionaryTests"> + </Test> + <Test + Identifier = "GPBStringDoubleDictionaryTests"> + </Test> + <Test + Identifier = "GPBStringEnumDictionaryTests"> + </Test> + <Test + Identifier = "GPBStringEnumDictionaryUnknownEnumTests"> + </Test> + <Test + Identifier = "GPBStringFloatDictionaryTests"> + </Test> + <Test + Identifier = "GPBStringInt32DictionaryTests"> + </Test> + <Test + Identifier = "GPBStringInt64DictionaryTests"> </Test> <Test Identifier = "GPBStringTests"> </Test> <Test + Identifier = "GPBStringUInt32DictionaryTests"> + </Test> + <Test + Identifier = "GPBStringUInt64DictionaryTests"> + </Test> + <Test Identifier = "GPBTestCase"> </Test> <Test - Identifier = "GeneratedMessageTests"> + Identifier = "GPBUInt32ArrayTests"> + </Test> + <Test + Identifier = "GPBUInt32BoolDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt32DoubleDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt32EnumDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt32EnumDictionaryUnknownEnumTests"> + </Test> + <Test + Identifier = "GPBUInt32FloatDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt32Int32DictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt32Int64DictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt32ObjectDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt32UInt32DictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt32UInt64DictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt64ArrayTests"> + </Test> + <Test + Identifier = "GPBUInt64BoolDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt64DoubleDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt64EnumDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt64EnumDictionaryUnknownEnumTests"> + </Test> + <Test + Identifier = "GPBUInt64FloatDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt64Int32DictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt64Int64DictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt64ObjectDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt64UInt32DictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt64UInt64DictionaryTests"> + </Test> + <Test + Identifier = "MessageMergeTests"> + </Test> + <Test + Identifier = "MessageRuntimeTests"> + </Test> + <Test + Identifier = "MessageSerializationTests"> </Test> <Test Identifier = "MessageTests"> @@ -72,6 +276,9 @@ Identifier = "UtilitiesTests"> </Test> <Test + Identifier = "WellKnownTypesTest"> + </Test> + <Test Identifier = "WireFormatTests"> </Test> </SkippedTests> diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme index 617fb47f..583a464a 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "0620" + LastUpgradeVersion = "0630" version = "1.3"> <BuildAction parallelizeBuildables = "YES" diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj index d6e621e6..23e9f169 100644 --- a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj @@ -6,20 +6,6 @@ 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 */; }; @@ -27,7 +13,7 @@ 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 */; }; + 7461B54C0F94FB4E00A0C422 /* GPBUnknownField.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4AF0F94F99000A0C422 /* GPBUnknownField.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 */; }; @@ -59,7 +45,6 @@ 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 */; }; @@ -73,15 +58,30 @@ 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 */; }; + F45C69CC16DFD08D0081955B /* GPBExtensionInternals.m in Sources */ = {isa = PBXBuildFile; fileRef = F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */; }; F45E57C91AE6DC98000B7D99 /* text_format_map_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F45E57C81AE6DC98000B7D99 /* text_format_map_unittest_data.txt */; }; + F4E675C81B21D1610054530B /* Any.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675B71B21D1440054530B /* Any.pbobjc.m */; }; + F4E675C91B21D1610054530B /* Api.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675B91B21D1440054530B /* Api.pbobjc.m */; }; + F4E675CA1B21D1610054530B /* Empty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675BC1B21D1440054530B /* Empty.pbobjc.m */; }; + F4E675CB1B21D1610054530B /* FieldMask.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675BE1B21D1440054530B /* FieldMask.pbobjc.m */; }; + F4E675CC1B21D1610054530B /* SourceContext.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C01B21D1440054530B /* SourceContext.pbobjc.m */; }; + F4E675CD1B21D1610054530B /* Struct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C21B21D1440054530B /* Struct.pbobjc.m */; }; + F4E675CE1B21D1610054530B /* Type.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C51B21D1440054530B /* Type.pbobjc.m */; }; + F4E675CF1B21D1610054530B /* Wrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C71B21D1440054530B /* Wrappers.pbobjc.m */; }; + F4E675D01B21D1620054530B /* Any.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675B71B21D1440054530B /* Any.pbobjc.m */; }; + F4E675D11B21D1620054530B /* Api.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675B91B21D1440054530B /* Api.pbobjc.m */; }; + F4E675D21B21D1620054530B /* Empty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675BC1B21D1440054530B /* Empty.pbobjc.m */; }; + F4E675D31B21D1620054530B /* FieldMask.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675BE1B21D1440054530B /* FieldMask.pbobjc.m */; }; + F4E675D41B21D1620054530B /* SourceContext.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C01B21D1440054530B /* SourceContext.pbobjc.m */; }; + F4E675D51B21D1620054530B /* Struct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C21B21D1440054530B /* Struct.pbobjc.m */; }; + F4E675D61B21D1620054530B /* Type.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C51B21D1440054530B /* Type.pbobjc.m */; }; + F4E675D71B21D1620054530B /* Wrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C71B21D1440054530B /* Wrappers.pbobjc.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -99,12 +99,12 @@ remoteGlobalIDString = 7461B52D0F94FAF800A0C422; remoteInfo = ProtocolBuffers; }; - 8BD3982014BE59EB0081D629 /* PBXContainerItemProxy */ = { + F45BBC121B0CDBBA002D064D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; proxyType = 1; - remoteGlobalIDString = 8BD3981414BE4AE70081D629; - remoteInfo = Compile_Protos; + remoteGlobalIDString = F45BBC0E1B0CDB50002D064D; + remoteInfo = "Compile Unittest Protos"; }; /* End PBXContainerItemProxy section */ @@ -122,8 +122,8 @@ 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>"; }; + 7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownField.h; sourceTree = "<group>"; }; + 7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownField.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>"; }; @@ -142,10 +142,7 @@ 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>"; }; @@ -153,7 +150,6 @@ 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>"; }; @@ -161,7 +157,6 @@ 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>"; }; @@ -186,12 +181,11 @@ 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>"; }; + 8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.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>"; }; @@ -216,16 +210,41 @@ 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>"; }; + F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionInternals.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>"; }; + F4B6B8B01A9CC99500892426 /* GPBUnknownField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownField_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>"; }; + F4B6B8B31A9CD1C600892426 /* GPBExtensionInternals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionInternals.h; sourceTree = "<group>"; }; F4B6B8B51A9CD1C600892426 /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRootObject_PackagePrivate.h; sourceTree = "<group>"; }; - F4B6B8BA1A9D343B00892426 /* unittest_name_mangling.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_name_mangling.proto; sourceTree = "<group>"; }; + F4CF31711B162EF500BD9B06 /* unittest_objc_startup.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc_startup.proto; sourceTree = "<group>"; }; + F4E675B61B21D1440054530B /* Any.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Any.pbobjc.h; path = google/protobuf/Any.pbobjc.h; sourceTree = "<group>"; }; + F4E675B71B21D1440054530B /* Any.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Any.pbobjc.m; path = google/protobuf/Any.pbobjc.m; sourceTree = "<group>"; }; + F4E675B81B21D1440054530B /* Api.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Api.pbobjc.h; path = google/protobuf/Api.pbobjc.h; sourceTree = "<group>"; }; + F4E675B91B21D1440054530B /* Api.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Api.pbobjc.m; path = google/protobuf/Api.pbobjc.m; sourceTree = "<group>"; }; + F4E675BA1B21D1440054530B /* Descriptor.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Descriptor.pbobjc.h; path = google/protobuf/Descriptor.pbobjc.h; sourceTree = "<group>"; }; + F4E675BB1B21D1440054530B /* Empty.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Empty.pbobjc.h; path = google/protobuf/Empty.pbobjc.h; sourceTree = "<group>"; }; + F4E675BC1B21D1440054530B /* Empty.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Empty.pbobjc.m; path = google/protobuf/Empty.pbobjc.m; sourceTree = "<group>"; }; + F4E675BD1B21D1440054530B /* FieldMask.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FieldMask.pbobjc.h; path = google/protobuf/FieldMask.pbobjc.h; sourceTree = "<group>"; }; + F4E675BE1B21D1440054530B /* FieldMask.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FieldMask.pbobjc.m; path = google/protobuf/FieldMask.pbobjc.m; sourceTree = "<group>"; }; + F4E675BF1B21D1440054530B /* SourceContext.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SourceContext.pbobjc.h; path = google/protobuf/SourceContext.pbobjc.h; sourceTree = "<group>"; }; + F4E675C01B21D1440054530B /* SourceContext.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SourceContext.pbobjc.m; path = google/protobuf/SourceContext.pbobjc.m; sourceTree = "<group>"; }; + F4E675C11B21D1440054530B /* Struct.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Struct.pbobjc.h; path = google/protobuf/Struct.pbobjc.h; sourceTree = "<group>"; }; + F4E675C21B21D1440054530B /* Struct.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Struct.pbobjc.m; path = google/protobuf/Struct.pbobjc.m; sourceTree = "<group>"; }; + F4E675C31B21D1440054530B /* Timestamp.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Timestamp.pbobjc.h; path = google/protobuf/Timestamp.pbobjc.h; sourceTree = "<group>"; }; + F4E675C41B21D1440054530B /* Type.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Type.pbobjc.h; path = google/protobuf/Type.pbobjc.h; sourceTree = "<group>"; }; + F4E675C51B21D1440054530B /* Type.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Type.pbobjc.m; path = google/protobuf/Type.pbobjc.m; sourceTree = "<group>"; }; + F4E675C61B21D1440054530B /* Wrappers.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Wrappers.pbobjc.h; path = google/protobuf/Wrappers.pbobjc.h; sourceTree = "<group>"; }; + F4E675C71B21D1440054530B /* Wrappers.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Wrappers.pbobjc.m; path = google/protobuf/Wrappers.pbobjc.m; sourceTree = "<group>"; }; + F4E675D81B21D1DE0054530B /* any.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = any.proto; path = ../src/google/protobuf/any.proto; sourceTree = "<group>"; }; + F4E675D91B21D1DE0054530B /* api.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = api.proto; path = ../src/google/protobuf/api.proto; sourceTree = "<group>"; }; + F4E675DA1B21D1DE0054530B /* empty.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = empty.proto; path = ../src/google/protobuf/empty.proto; sourceTree = "<group>"; }; + F4E675DB1B21D1DE0054530B /* field_mask.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = field_mask.proto; path = ../src/google/protobuf/field_mask.proto; sourceTree = "<group>"; }; + F4E675DC1B21D1DE0054530B /* source_context.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = source_context.proto; path = ../src/google/protobuf/source_context.proto; sourceTree = "<group>"; }; + F4E675DD1B21D1DE0054530B /* struct.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = struct.proto; path = ../src/google/protobuf/struct.proto; sourceTree = "<group>"; }; + F4E675DE1B21D1DE0054530B /* type.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = type.proto; path = ../src/google/protobuf/type.proto; sourceTree = "<group>"; }; + F4E675DF1B21D1DE0054530B /* wrappers.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = wrappers.proto; path = ../src/google/protobuf/wrappers.proto; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -309,15 +328,39 @@ 29B97315FDCFA39411CA2CEA /* Generated */ = { isa = PBXGroup; children = ( - 8B4249491A92A0BA00BC1EC6 /* descriptor.proto */, + F4E675B61B21D1440054530B /* Any.pbobjc.h */, + F4E675B71B21D1440054530B /* Any.pbobjc.m */, + F4E675D81B21D1DE0054530B /* any.proto */, + F4E675B81B21D1440054530B /* Api.pbobjc.h */, + F4E675B91B21D1440054530B /* Api.pbobjc.m */, + F4E675D91B21D1DE0054530B /* api.proto */, + F4E675BA1B21D1440054530B /* Descriptor.pbobjc.h */, 8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */, - 8B54585814DCC34E003D7338 /* Descriptor.pbobjc.h */, - 8B42494A1A92A0BA00BC1EC6 /* duration.proto */, + 8B4249491A92A0BA00BC1EC6 /* descriptor.proto */, 8B4248DD1A929C7D00BC1EC6 /* Duration.pbobjc.h */, 8B4248DE1A929C7D00BC1EC6 /* Duration.pbobjc.m */, - 8B4249481A92A02300BC1EC6 /* timestamp.proto */, - 8B4248DF1A929C7D00BC1EC6 /* Timestamp.pbobjc.h */, + 8B42494A1A92A0BA00BC1EC6 /* duration.proto */, + F4E675BB1B21D1440054530B /* Empty.pbobjc.h */, + F4E675BC1B21D1440054530B /* Empty.pbobjc.m */, + F4E675DA1B21D1DE0054530B /* empty.proto */, + F4E675DB1B21D1DE0054530B /* field_mask.proto */, + F4E675BD1B21D1440054530B /* FieldMask.pbobjc.h */, + F4E675BE1B21D1440054530B /* FieldMask.pbobjc.m */, + F4E675DC1B21D1DE0054530B /* source_context.proto */, + F4E675BF1B21D1440054530B /* SourceContext.pbobjc.h */, + F4E675C01B21D1440054530B /* SourceContext.pbobjc.m */, + F4E675C11B21D1440054530B /* Struct.pbobjc.h */, + F4E675C21B21D1440054530B /* Struct.pbobjc.m */, + F4E675DD1B21D1DE0054530B /* struct.proto */, + F4E675C31B21D1440054530B /* Timestamp.pbobjc.h */, 8B4248E01A929C7D00BC1EC6 /* Timestamp.pbobjc.m */, + 8B4249481A92A02300BC1EC6 /* timestamp.proto */, + F4E675C41B21D1440054530B /* Type.pbobjc.h */, + F4E675C51B21D1440054530B /* Type.pbobjc.m */, + F4E675DE1B21D1DE0054530B /* type.proto */, + F4E675C61B21D1440054530B /* Wrappers.pbobjc.h */, + F4E675C71B21D1440054530B /* Wrappers.pbobjc.m */, + F4E675DF1B21D1DE0054530B /* wrappers.proto */, ); name = Generated; sourceTree = "<group>"; @@ -335,9 +378,8 @@ 7461B3C50F94F84100A0C422 /* Extensions */ = { isa = PBXGroup; children = ( - F4B6B8B31A9CD1C600892426 /* GPBExtensionField_PackagePrivate.h */, - 748F0CAF0FD70602000858A9 /* GPBExtensionField.h */, - F45C69CB16DFD08D0081955B /* GPBExtensionField.m */, + F4B6B8B31A9CD1C600892426 /* GPBExtensionInternals.h */, + F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */, 7461B4A80F94F99000A0C422 /* GPBExtensionRegistry.h */, 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */, F4B6B8B51A9CD1C600892426 /* GPBRootObject_PackagePrivate.h */, @@ -350,9 +392,9 @@ 7461B4850F94F96600A0C422 /* Fields */ = { isa = PBXGroup; children = ( - F4B6B8B01A9CC99500892426 /* GPBField_PackagePrivate.h */, - 7461B4AE0F94F99000A0C422 /* GPBField.h */, - 7461B4AF0F94F99000A0C422 /* GPBField.m */, + F4B6B8B01A9CC99500892426 /* GPBUnknownField_PackagePrivate.h */, + 7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */, + 7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */, F4B6B8B11A9CCBBB00892426 /* GPBUnknownFieldSet_PackagePrivate.h */, 7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */, 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */, @@ -392,8 +434,6 @@ children = ( 8B9A5EA91831993600A9D33B /* iOSTestHarness */, 8B4248B71A8BDD9600BC1EC6 /* protobuf */, - 8B20A9A816F1BBFA00BE3EAD /* Filter1.txt */, - F44B25D81A729803005CCF68 /* Filter2.txt */, 8B210CCD159383D60032D72D /* golden_message */, 8B210CCF159386920032D72D /* golden_packed_fields_message */, 8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */, @@ -409,7 +449,6 @@ 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 */, @@ -431,13 +470,12 @@ 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 */, + F4CF31711B162EF500BD9B06 /* unittest_objc_startup.proto */, 8B7E6A7D14893DBC00F8884A /* unittest_optimize_for.proto */, F4487C7A1AADFB5500531423 /* unittest_runtime_proto2.proto */, F4487C7B1AADFB5500531423 /* unittest_runtime_proto3.proto */, @@ -478,7 +516,7 @@ F43725921AC9835D004DCAFB /* GPBDictionary_PackagePrivate.h */, F4353D241ABB156F005A6198 /* GPBDictionary.h */, F4353D251ABB156F005A6198 /* GPBDictionary.m */, - 8BEB5AE01498033E0078BF9D /* GPBTypes.h */, + 8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */, F4487C7D1AAE06C500531423 /* GPBUtilities_PackagePrivate.h */, 7461B4E50F94F99000A0C422 /* GPBUtilities.h */, 7461B4E60F94F99000A0C422 /* GPBUtilities.m */, @@ -507,6 +545,23 @@ }; /* End PBXHeadersBuildPhase section */ +/* Begin PBXLegacyTarget section */ + F45BBC0E1B0CDB50002D064D /* Compile Unittest Protos */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "$(ACTION)"; + buildConfigurationList = F45BBC111B0CDB50002D064D /* Build configuration list for PBXLegacyTarget "Compile Unittest Protos" */; + buildPhases = ( + ); + buildToolPath = DevTools/compile_testing_protos.sh; + buildWorkingDirectory = ""; + dependencies = ( + ); + name = "Compile Unittest Protos"; + passBuildSettingsInEnvironment = 1; + productName = "Compile Unittest Protos"; + }; +/* End PBXLegacyTarget section */ + /* Begin PBXNativeTarget section */ 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */ = { isa = PBXNativeTarget; @@ -555,7 +610,7 @@ ); dependencies = ( 8BBEA4BD147C729A00C4ADB7 /* PBXTargetDependency */, - 8BD3982114BE59EB0081D629 /* PBXTargetDependency */, + F45BBC131B0CDBBA002D064D /* PBXTargetDependency */, 8B9A5ED11831994600A9D33B /* PBXTargetDependency */, ); name = UnitTests; @@ -587,11 +642,14 @@ isa = PBXProject; attributes = { LastTestingUpgradeCheck = 0600; - LastUpgradeCheck = 0610; + LastUpgradeCheck = 0630; TargetAttributes = { 8BBEA4A5147C727100C4ADB7 = { TestTargetID = 8B9A5EA41831993600A9D33B; }; + F45BBC0E1B0CDB50002D064D = { + CreatedOnToolsVersion = 6.3.2; + }; }; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProtocolBuffers_iOS" */; @@ -607,9 +665,9 @@ targets = ( 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */, 8BBEA4A5147C727100C4ADB7 /* UnitTests */, - 8BD3981414BE4AE70081D629 /* Compile_Protos */, 8B9A5EA41831993600A9D33B /* iOSTestHarness */, F4487C551A9F8F8100531423 /* TestSingleSourceBuild */, + F45BBC0E1B0CDB50002D064D /* Compile Unittest Protos */, ); }; /* End PBXProject section */ @@ -639,51 +697,6 @@ /* 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\n# Use the filter\nexport GPB_OBJC_CLASS_WHITELIST_PATHS=\"${SRCROOT}/Tests/Filter1.txt;${SRCROOT}/Tests/Filter2.txt\"\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; @@ -708,19 +721,27 @@ files = ( 2CFB390415C718CE00CBF84D /* Descriptor.pbobjc.m in Sources */, 7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */, + F4E675D21B21D1620054530B /* Empty.pbobjc.m in Sources */, F4487C731A9F906200531423 /* GPBArray.m in Sources */, 7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */, 7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */, - 7461B54C0F94FB4E00A0C422 /* GPBField.m in Sources */, + F4E675D31B21D1620054530B /* FieldMask.pbobjc.m in Sources */, + 7461B54C0F94FB4E00A0C422 /* GPBUnknownField.m in Sources */, 7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */, 7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */, 7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */, 7461B5640F94FB4E00A0C422 /* GPBWireFormat.m in Sources */, + F4E675D11B21D1620054530B /* Api.pbobjc.m in Sources */, + F4E675D41B21D1620054530B /* SourceContext.pbobjc.m in Sources */, F4353D271ABB156F005A6198 /* GPBDictionary.m in Sources */, 8B79657B14992E3F002FFBFC /* GPBRootObject.m in Sources */, 8B96157414C8C38C00A2AC0B /* GPBDescriptor.m in Sources */, - F45C69CC16DFD08D0081955B /* GPBExtensionField.m in Sources */, + F4E675D01B21D1620054530B /* Any.pbobjc.m in Sources */, + F45C69CC16DFD08D0081955B /* GPBExtensionInternals.m in Sources */, 8B4248E41A929C8900BC1EC6 /* GPBWellKnownTypes.m in Sources */, + F4E675D61B21D1620054530B /* Type.pbobjc.m in Sources */, + F4E675D51B21D1620054530B /* Struct.pbobjc.m in Sources */, + F4E675D71B21D1620054530B /* Wrappers.pbobjc.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -741,12 +762,18 @@ F4353D441AC06F31005A6198 /* GPBDictionaryTests+Int64.m in Sources */, F4353D471AC06F31005A6198 /* GPBDictionaryTests+UInt64.m in Sources */, 8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */, + F4E675CC1B21D1610054530B /* SourceContext.pbobjc.m in Sources */, 8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */, F4487C811AAF62FC00531423 /* GPBMessageTests+Serialization.m in Sources */, 8B4248E61A929C9900BC1EC6 /* GPBWellKnownTypesTest.m in Sources */, + F4E675CA1B21D1610054530B /* Empty.pbobjc.m in Sources */, + F4E675CE1B21D1610054530B /* Type.pbobjc.m in Sources */, F4353D1F1AB88243005A6198 /* GPBDescriptorTests.m in Sources */, + F4E675CF1B21D1610054530B /* Wrappers.pbobjc.m in Sources */, + F4E675C81B21D1610054530B /* Any.pbobjc.m in Sources */, 8B4248B41A8BD96E00BC1EC6 /* GPBSwiftTests.swift in Sources */, 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */, + F4E675CD1B21D1610054530B /* Struct.pbobjc.m in Sources */, F4487C771AADF84900531423 /* GPBMessageTests+Runtime.m in Sources */, F4353D431AC06F31005A6198 /* GPBDictionaryTests+Int32.m in Sources */, 8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */, @@ -761,9 +788,10 @@ 8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */, 8B79657D14992E3F002FFBFC /* GPBRootObject.m in Sources */, 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */, + F4E675CB1B21D1610054530B /* FieldMask.pbobjc.m in Sources */, 8B96157514CA019D00A2AC0B /* Descriptor.pbobjc.m in Sources */, - 8BCC29BF16FD09A000F29F4A /* GPBFilteredMessageTests.m in Sources */, 8B8B615D17DF7056002EE618 /* GPBARCUnittestProtos.m in Sources */, + F4E675C91B21D1610054530B /* Api.pbobjc.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -771,7 +799,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - F4487C5B1A9F8F8100531423 /* Descriptor.pbobjc.m in Sources */, F4487C6F1A9F8FFF00531423 /* GPBProtocolBuffers.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -789,10 +816,10 @@ target = 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */; targetProxy = 8BBEA4BC147C729A00C4ADB7 /* PBXContainerItemProxy */; }; - 8BD3982114BE59EB0081D629 /* PBXTargetDependency */ = { + F45BBC131B0CDBBA002D064D /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 8BD3981414BE4AE70081D629 /* Compile_Protos */; - targetProxy = 8BD3982014BE59EB0081D629 /* PBXContainerItemProxy */; + target = F45BBC0E1B0CDB50002D064D /* Compile Unittest Protos */; + targetProxy = F45BBC121B0CDBBA002D064D /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ @@ -909,20 +936,6 @@ }; 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 = { @@ -1029,6 +1042,18 @@ }; name = Release; }; + F45BBC0F1B0CDB50002D064D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + F45BBC101B0CDB50002D064D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -1059,15 +1084,6 @@ 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 = ( @@ -1086,6 +1102,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + F45BBC111B0CDB50002D064D /* Build configuration list for PBXLegacyTarget "Compile Unittest Protos" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F45BBC0F1B0CDB50002D064D /* Debug */, + F45BBC101B0CDB50002D064D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme index f5479ba2..4898eb5f 100644 --- a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme +++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "0610" + LastUpgradeVersion = "0630" version = "1.3"> <BuildAction parallelizeBuildables = "YES" @@ -39,9 +39,6 @@ </BuildableReference> <SkippedTests> <Test - Identifier = "ArrayTests"> - </Test> - <Test Identifier = "CodedInputStreamTests"> </Test> <Test @@ -51,16 +48,223 @@ Identifier = "ConcurrencyTests"> </Test> <Test - Identifier = "FilteredMessageTests"> + Identifier = "DescriptorTests"> + </Test> + <Test + Identifier = "GPBBoolArrayTests"> + </Test> + <Test + Identifier = "GPBBoolBoolDictionaryTests"> + </Test> + <Test + Identifier = "GPBBoolDoubleDictionaryTests"> + </Test> + <Test + Identifier = "GPBBoolFloatDictionaryTests"> + </Test> + <Test + Identifier = "GPBBoolInt32DictionaryTests"> + </Test> + <Test + Identifier = "GPBBoolInt64DictionaryTests"> + </Test> + <Test + Identifier = "GPBBoolObjectDictionaryTests"> + </Test> + <Test + Identifier = "GPBBoolUInt32DictionaryTests"> + </Test> + <Test + Identifier = "GPBBoolUInt64DictionaryTests"> + </Test> + <Test + Identifier = "GPBBridgeTests"> + </Test> + <Test + Identifier = "GPBDoubleArrayTests"> + </Test> + <Test + Identifier = "GPBEnumArrayCustomTests"> + </Test> + <Test + Identifier = "GPBEnumArrayTests"> + </Test> + <Test + Identifier = "GPBFloatArrayTests"> + </Test> + <Test + Identifier = "GPBInt32ArrayTests"> + </Test> + <Test + Identifier = "GPBInt32BoolDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt32DoubleDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt32EnumDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt32EnumDictionaryUnknownEnumTests"> + </Test> + <Test + Identifier = "GPBInt32FloatDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt32Int32DictionaryTests"> + </Test> + <Test + Identifier = "GPBInt32Int64DictionaryTests"> + </Test> + <Test + Identifier = "GPBInt32ObjectDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt32UInt32DictionaryTests"> + </Test> + <Test + Identifier = "GPBInt32UInt64DictionaryTests"> + </Test> + <Test + Identifier = "GPBInt64ArrayTests"> + </Test> + <Test + Identifier = "GPBInt64BoolDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt64DoubleDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt64EnumDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt64EnumDictionaryUnknownEnumTests"> + </Test> + <Test + Identifier = "GPBInt64FloatDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt64Int32DictionaryTests"> + </Test> + <Test + Identifier = "GPBInt64Int64DictionaryTests"> + </Test> + <Test + Identifier = "GPBInt64ObjectDictionaryTests"> + </Test> + <Test + Identifier = "GPBInt64UInt32DictionaryTests"> + </Test> + <Test + Identifier = "GPBInt64UInt64DictionaryTests"> + </Test> + <Test + Identifier = "GPBStringBoolDictionaryTests"> + </Test> + <Test + Identifier = "GPBStringDoubleDictionaryTests"> + </Test> + <Test + Identifier = "GPBStringEnumDictionaryTests"> + </Test> + <Test + Identifier = "GPBStringEnumDictionaryUnknownEnumTests"> + </Test> + <Test + Identifier = "GPBStringFloatDictionaryTests"> + </Test> + <Test + Identifier = "GPBStringInt32DictionaryTests"> + </Test> + <Test + Identifier = "GPBStringInt64DictionaryTests"> </Test> <Test Identifier = "GPBStringTests"> </Test> <Test + Identifier = "GPBStringUInt32DictionaryTests"> + </Test> + <Test + Identifier = "GPBStringUInt64DictionaryTests"> + </Test> + <Test Identifier = "GPBTestCase"> </Test> <Test - Identifier = "GeneratedMessageTests"> + Identifier = "GPBUInt32ArrayTests"> + </Test> + <Test + Identifier = "GPBUInt32BoolDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt32DoubleDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt32EnumDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt32EnumDictionaryUnknownEnumTests"> + </Test> + <Test + Identifier = "GPBUInt32FloatDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt32Int32DictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt32Int64DictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt32ObjectDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt32UInt32DictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt32UInt64DictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt64ArrayTests"> + </Test> + <Test + Identifier = "GPBUInt64BoolDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt64DoubleDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt64EnumDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt64EnumDictionaryUnknownEnumTests"> + </Test> + <Test + Identifier = "GPBUInt64FloatDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt64Int32DictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt64Int64DictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt64ObjectDictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt64UInt32DictionaryTests"> + </Test> + <Test + Identifier = "GPBUInt64UInt64DictionaryTests"> + </Test> + <Test + Identifier = "MessageMergeTests"> + </Test> + <Test + Identifier = "MessageRuntimeTests"> + </Test> + <Test + Identifier = "MessageSerializationTests"> </Test> <Test Identifier = "MessageTests"> @@ -72,6 +276,9 @@ Identifier = "UtilitiesTests"> </Test> <Test + Identifier = "WellKnownTypesTest"> + </Test> + <Test Identifier = "WireFormatTests"> </Test> </SkippedTests> @@ -96,7 +303,8 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" allowLocationSimulation = "YES"> - <BuildableProductRunnable> + <BuildableProductRunnable + runnableDebuggingMode = "0"> <BuildableReference BuildableIdentifier = "primary" BlueprintIdentifier = "8B9A5EA41831993600A9D33B" diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme index c3c2c7d4..19267fc3 100644 --- a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme +++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "0610" + LastUpgradeVersion = "0630" version = "1.3"> <BuildAction parallelizeBuildables = "YES" diff --git a/objectivec/README.md b/objectivec/README.md index 186e45b2..134bf1ab 100644 --- a/objectivec/README.md +++ b/objectivec/README.md @@ -21,15 +21,15 @@ Installation ------------ The full distribution pulled from github includes the sources for both the -compiler (protoc) and the runtime (this directory). To build the compiler +compiler (protoc) and the runtime (this directory). To build the compiler and run the runtime tests, you can use: $ objectivec/DevTools/full_mac_build.sh This will generate the `src/protoc` binary. -Usage ------ +Building +-------- There are two ways to include the Runtime sources in your project: @@ -47,6 +47,80 @@ If the target is using ARC, remember to turn off ARC (`-fno-objc-arc`) for the The files generated by `protoc` for the `*.proto` files (`\*.pbobjc.h' and `\*.pbobjc.m`) are then also added to the target. +Usage +----- + +The objects generated for messages should work like any other Objective C +object. They are mutable objects, but if you don't change them, they are safe +to share between threads (similar to passing an NSMutableDictionary between +threads/queues; as long as no one mutates it, things are fine). + +There are a few behaviors worth calling out: + +A property that is type NSString\* will never return nil. If the value is +unset, it will return an empty string (@""). This is inpart to align things +with the Protocol Buffers spec which says the default for strings is an empty +string, but also so you can always safely pass them to isEqual:/compare:, etc. +and have deterministic results. + +A property that is type NSData\* also won't return nil, it will return an empty +data ([NSData data]). The reasoning is the same as for NSString not returning +nil. + +A property that is another GPBMessage class also will not return nil. If the +field wasn't already set, you will get a instance of the correct class. This +instance will be a temporary instance unless you mutate it, at which point it +will be attached to its parent object. We call this pattern *autocreators*. +Similar to NSString and NSData properties it makes things a little safer when +using them with isEqual:/etc.; but more importantly, this allows you to write +code that uses Objective C's property dot notation to walk into nested objects +and access and/or assign things without having to check that they are not nil +and create them each step along the way. You can write this: + +``` +- (void)updateRecord:(MyMessage *)msg { + ... + // Note: You don't have to check subMessage and otherMessage for nil and + // alloc/init/assign them back along the way. + msg.subMessage.otherMessage.lastName = @"Smith"; + ... +} +``` + +If you want to check if a GPBMessage property is present, there is always as +`has\[NAME\]` property to go with the main property to check if it is set. + +A property that is of an Array or Dictionary type also provides *autocreator* +behavior and will never return nil. This provides all the same benefits you +see for the message properties. Again, you can write: + +``` +- (void)updateRecord:(MyMessage *)msg { + ... + // Note: Just like above, you don't have to check subMessage and otherMessage + // for nil and alloc/init/assign them back along the way. You also don't have + // to create the siblingsArray, you can safely just append to it. + [msg.subMessage.otherMessage.siblingsArray addObject:@"Pat"]; + ... +} +``` + +If you are inspecting a message you got from some other place (server, disk, +etc), you may want to check if the Array or Dictionary has entries without +causing it to be created for you. For this, there is always a `\[NAME\]_Count` +property also provided that can return zero or the real count, but won't trigger +the creation. + +For primitive type fields (ints, floats, bools, enum) in messages defined in a +`.proto` file that use *proto2* syntax there are conceptual differences between +having an *explicit* and *default* value. You can always get the value of the +property. In the case that it hasn't been set you will get the default. In +cases where you need to know whether it was set explicitly or you are just +getting the default, you can use the `has\[NAME\]` property. If the value has +been set, and you want to clear it, you can set the `has\[NAME\]` to `NO`. +*proto3* syntax messages do away with this concept, thus the default values are +never included when the message is encoded. + The Objective C classes/enums can be used from Swift code. Objective C Generator Options @@ -55,18 +129,19 @@ Objective C Generator Options **objc_class_prefix=\<prefix\>** (no default) Since Objective C uses a global namespace for all of its classes, there can -be collisions. This option provides a prefix that will be added to the Enums -and Objects (for messages) generated from the proto. Convention is to base +be collisions. This option provides a prefix that will be added to the Enums +and Objects (for messages) generated from the proto. Convention is to base the prefix on the package the proto is in. Contributing ------------ Please make updates to the tests along with changes. If just changing the -runtime, the Xcode projects can be used to build and run tests. If change also -require changes to the generated code, `objectivec/DevTools/full_mac_build.sh` -can be used to easily rebuild and test changes. Passing `-h` to the script will -show the addition options that could be useful. +runtime, the Xcode projects can be used to build and run tests. If your change +also requires changes to the generated code, +`objectivec/DevTools/full_mac_build.sh` can be used to easily rebuild and test +changes. Passing `-h` to the script will show the addition options that could +be useful. Documentation ------------- diff --git a/objectivec/Tests/GPBARCUnittestProtos.m b/objectivec/Tests/GPBARCUnittestProtos.m index daf4effc..d0408869 100644 --- a/objectivec/Tests/GPBARCUnittestProtos.m +++ b/objectivec/Tests/GPBARCUnittestProtos.m @@ -41,16 +41,15 @@ #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/UnittestObjcStartup.pbobjc.h" #import "google/protobuf/UnittestOptimizeFor.pbobjc.h" #import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.h" #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h" diff --git a/objectivec/Tests/GPBCodedInputStreamTests.m b/objectivec/Tests/GPBCodedInputStreamTests.m index 5f29d7c8..579fe65c 100644 --- a/objectivec/Tests/GPBCodedInputStreamTests.m +++ b/objectivec/Tests/GPBCodedInputStreamTests.m @@ -260,7 +260,7 @@ [GPBCodedInputStream streamWithData:[NSMutableData dataWithData:data]]; XCTAssertEqual(tag, [input readTag]); - XCTAssertThrows([input readData]); + XCTAssertThrows([input readBytes]); } // Verifies fix for b/10315336. diff --git a/objectivec/Tests/GPBConcurrencyTests.m b/objectivec/Tests/GPBConcurrencyTests.m index e500ad77..daf75e7e 100644 --- a/objectivec/Tests/GPBConcurrencyTests.m +++ b/objectivec/Tests/GPBConcurrencyTests.m @@ -196,7 +196,8 @@ static const int kNumMessages = 100; NSArray *threads = [self createThreadsWithSelector:sel object:messages]; [self startThreads:threads]; [self joinThreads:threads]; - GPBExtensionField *extension = [UnittestRoot optionalForeignMessageExtension]; + GPBExtensionDescriptor *extension = + [UnittestRoot optionalForeignMessageExtension]; for (TestAllExtensions *message in messages) { XCTAssertFalse([message hasExtension:extension]); } diff --git a/objectivec/Tests/GPBFilteredMessageTests.m b/objectivec/Tests/GPBFilteredMessageTests.m deleted file mode 100644 index b0588837..00000000 --- a/objectivec/Tests/GPBFilteredMessageTests.m +++ /dev/null @@ -1,98 +0,0 @@ -// 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+Runtime.m b/objectivec/Tests/GPBMessageTests+Runtime.m index 4621f90f..8942a843 100644 --- a/objectivec/Tests/GPBMessageTests+Runtime.m +++ b/objectivec/Tests/GPBMessageTests+Runtime.m @@ -36,6 +36,7 @@ #import "google/protobuf/MapUnittest.pbobjc.h" #import "google/protobuf/Unittest.pbobjc.h" +#import "google/protobuf/UnittestObjcStartup.pbobjc.h" #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h" #import "google/protobuf/UnittestRuntimeProto3.pbobjc.h" @@ -47,6 +48,14 @@ // TODO(thomasvl): Pull tests over from GPBMessageTests that are runtime // specific. +- (void)testStartupOrdering { + // Just have to create a message. Nothing else uses the classes from + // this file, so the first selector invoked on the class will initialize + // it, which also initializes the root. + TestObjCStartupMessage *message = [TestObjCStartupMessage message]; + XCTAssertNotNil(message); +} + - (void)testProto2HasMethodSupport { NSArray *names = @[ @"Int32", @@ -70,8 +79,8 @@ ]; // Proto2 gets: - // - has* on all non repeated fields. - // - setHas* on all non repeated fields. + + // Single fields - has*/setHas* is valid. for (NSString *name in names) { // build the selector, i.e. - hasOptionalInt32/setHasOptionalInt32: @@ -85,21 +94,28 @@ name); } - // Repeated - no has/setHas + // Repeated fields + // - no has*/setHas* + // - *Count for (NSString *name in names) { - // build the selector, i.e. - hasRepeatedInt32/setHasRepeatedInt32: + // build the selector, i.e. - hasRepeatedInt32Array/setHasRepeatedInt32Array: SEL hasSel = NSSelectorFromString( - [NSString stringWithFormat:@"hasRepeated%@", name]); + [NSString stringWithFormat:@"hasRepeated%@Array", name]); SEL setHasSel = NSSelectorFromString( - [NSString stringWithFormat:@"setHasRepeated%@:", name]); + [NSString stringWithFormat:@"setHasRepeated%@Array:", name]); XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@", name); XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel], @"field: %@", name); + // build the selector, i.e. - repeatedInt32Array_Count + SEL countSel = NSSelectorFromString( + [NSString stringWithFormat:@"repeated%@Array_Count", name]); + XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@", + name); } - // Oneofs - no has/setHas + // OneOf fields - no has*/setHas* for (NSString *name in names) { // build the selector, i.e. - hasOneofInt32/setHasOneofInt32: @@ -112,6 +128,50 @@ XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel], @"field: %@", name); } + + // map<> fields + // - no has*/setHas* + // - *Count + + NSArray *mapNames = @[ + @"Int32Int32", + @"Int64Int64", + @"Uint32Uint32", + @"Uint64Uint64", + @"Sint32Sint32", + @"Sint64Sint64", + @"Fixed32Fixed32", + @"Fixed64Fixed64", + @"Sfixed32Sfixed32", + @"Sfixed64Sfixed64", + @"Int32Float", + @"Int32Double", + @"BoolBool", + @"StringString", + @"StringBytes", + @"StringMessage", + @"Int32Bytes", + @"Int32Enum", + @"Int32Message", + ]; + + for (NSString *name in mapNames) { + // build the selector, i.e. - hasMapInt32Int32/setHasMapInt32Int32: + SEL hasSel = NSSelectorFromString( + [NSString stringWithFormat:@"hasMap%@", name]); + SEL setHasSel = NSSelectorFromString( + [NSString stringWithFormat:@"setHasMap%@:", name]); + XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@", + name); + XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel], + @"field: %@", name); + // build the selector, i.e. - mapInt32Int32Count + SEL countSel = NSSelectorFromString( + [NSString stringWithFormat:@"map%@_Count", name]); + XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@", + name); + } + } - (void)testProto3HasMethodSupport { @@ -136,10 +196,10 @@ ]; // Proto3 gets: - // - has* on non repeated message fields. - // - setHas* on all non repeated message fields. - // Singlular + // Single fields + // - has*/setHas* invalid for primative types. + // - has*/setHas* valid for Message. for (NSString *name in names) { // build the selector, i.e. - hasOptionalInt32/setHasOptionalInt32: @@ -147,7 +207,7 @@ [NSString stringWithFormat:@"hasOptional%@", name]); SEL setHasSel = NSSelectorFromString( [NSString stringWithFormat:@"setHasOptional%@:", name]); - if ([name isEqual:@"Group"] || [name isEqual:@"Message"]) { + if ([name isEqual:@"Message"]) { // Sub messages/groups are the exception. XCTAssertTrue([Message3 instancesRespondToSelector:hasSel], @"field: %@", name); @@ -161,21 +221,28 @@ } } - // Repeated - no has/setHas + // Repeated fields + // - no has*/setHas* + // - *Count for (NSString *name in names) { - // build the selector, i.e. - hasRepeatedInt32/setHasRepeatedInt32: + // build the selector, i.e. - hasRepeatedInt32Array/setHasRepeatedInt32Array: SEL hasSel = NSSelectorFromString( - [NSString stringWithFormat:@"hasRepeated%@", name]); + [NSString stringWithFormat:@"hasRepeated%@Array", name]); SEL setHasSel = NSSelectorFromString( - [NSString stringWithFormat:@"setHasRepeated%@:", name]); + [NSString stringWithFormat:@"setHasRepeated%@Array:", name]); XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@", name); XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel], @"field: %@", name); + // build the selector, i.e. - repeatedInt32Array_Count + SEL countSel = NSSelectorFromString( + [NSString stringWithFormat:@"repeated%@Array_Count", name]); + XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@", + name); } - // Oneofs - no has/setHas + // OneOf fields - no has*/setHas* for (NSString *name in names) { // build the selector, i.e. - hasOneofInt32/setHasOneofInt32: @@ -188,6 +255,49 @@ XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel], @"field: %@", name); } + + // map<> fields + // - no has*/setHas* + // - *Count + + NSArray *mapNames = @[ + @"Int32Int32", + @"Int64Int64", + @"Uint32Uint32", + @"Uint64Uint64", + @"Sint32Sint32", + @"Sint64Sint64", + @"Fixed32Fixed32", + @"Fixed64Fixed64", + @"Sfixed32Sfixed32", + @"Sfixed64Sfixed64", + @"Int32Float", + @"Int32Double", + @"BoolBool", + @"StringString", + @"StringBytes", + @"StringMessage", + @"Int32Bytes", + @"Int32Enum", + @"Int32Message", + ]; + + for (NSString *name in mapNames) { + // build the selector, i.e. - hasMapInt32Int32/setHasMapInt32Int32: + SEL hasSel = NSSelectorFromString( + [NSString stringWithFormat:@"hasMap%@", name]); + SEL setHasSel = NSSelectorFromString( + [NSString stringWithFormat:@"setHasMap%@:", name]); + XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@", + name); + XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel], + @"field: %@", name); + // build the selector, i.e. - mapInt32Int32Count + SEL countSel = NSSelectorFromString( + [NSString stringWithFormat:@"map%@_Count", name]); + XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@", + name); + } } - (void)testProto2SingleFieldHasBehavior { diff --git a/objectivec/Tests/GPBMessageTests+Serialization.m b/objectivec/Tests/GPBMessageTests+Serialization.m index 6d5527b5..ae4be9e5 100644 --- a/objectivec/Tests/GPBMessageTests+Serialization.m +++ b/objectivec/Tests/GPBMessageTests+Serialization.m @@ -36,6 +36,7 @@ #import "google/protobuf/MapProto2Unittest.pbobjc.h" #import "google/protobuf/MapUnittest.pbobjc.h" +#import "google/protobuf/Unittest.pbobjc.h" #import "google/protobuf/UnittestDropUnknownFields.pbobjc.h" #import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.h" #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h" @@ -166,17 +167,15 @@ static NSData *DataFromCStr(const char *str) { [unknownFields hasField:Message2_FieldNumber_RepeatedEnumArray]); XCTAssertTrue([unknownFields hasField:Message2_FieldNumber_OneofEnum]); - GPBField *field = [unknownFields getField:Message2_FieldNumber_OptionalEnum]; + GPBUnknownField *field = + [unknownFields getField:Message2_FieldNumber_OptionalEnum]; XCTAssertEqual(field.varintList.count, 1U); XCTAssertEqual([field.varintList valueAtIndex:0], (uint64_t)Message3_Enum_Extra3); - // Repeated in proto3 default to packed, so this will be length delimited - // unknown field, and the value (Message3_Enum_Extra3) encodes into one byte. field = [unknownFields getField:Message2_FieldNumber_RepeatedEnumArray]; - XCTAssertEqual(field.lengthDelimitedList.count, 1U); - NSData *expected = DataFromCStr("\x1E"); - XCTAssertEqualObjects([field.lengthDelimitedList objectAtIndex:0], expected); + 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); @@ -678,6 +677,131 @@ static NSData *DataFromCStr(const char *str) { //%PDDM-EXPAND-END (2 expansions) +- (void)testPackedUnpackedMessageParsing { + // packed is optional, a repeated field should parse when packed or unpacked. + + TestPackedTypes *packedOrig = [TestPackedTypes message]; + TestUnpackedTypes *unpackedOrig = [TestUnpackedTypes message]; + [self setPackedFields:packedOrig repeatedCount:4]; + [self setUnpackedFields:unpackedOrig repeatedCount:4]; + + NSData *packedData = [packedOrig data]; + NSData *unpackedData = [unpackedOrig data]; + XCTAssertNotNil(packedData); + XCTAssertNotNil(unpackedData); + XCTAssertNotEqualObjects(packedData, unpackedData, + @"Data should differ (packed vs unpacked) use"); + + NSError *error = nil; + TestPackedTypes *packedParse = + [TestPackedTypes parseFromData:unpackedData error:&error]; + XCTAssertNotNil(packedParse); + XCTAssertNil(error); + XCTAssertEqualObjects(packedParse, packedOrig); + + error = nil; + TestUnpackedTypes *unpackedParsed = + [TestUnpackedTypes parseFromData:packedData error:&error]; + XCTAssertNotNil(unpackedParsed); + XCTAssertNil(error); + XCTAssertEqualObjects(unpackedParsed, unpackedOrig); +} + +- (void)testPackedUnpackedExtensionParsing { + // packed is optional, a repeated extension should parse when packed or + // unpacked. + + TestPackedExtensions *packedOrig = [TestPackedExtensions message]; + TestUnpackedExtensions *unpackedOrig = [TestUnpackedExtensions message]; + [self setPackedExtensions:packedOrig repeatedCount:kGPBDefaultRepeatCount]; + [self setUnpackedExtensions:unpackedOrig repeatedCount:kGPBDefaultRepeatCount]; + + NSData *packedData = [packedOrig data]; + NSData *unpackedData = [unpackedOrig data]; + XCTAssertNotNil(packedData); + XCTAssertNotNil(unpackedData); + XCTAssertNotEqualObjects(packedData, unpackedData, + @"Data should differ (packed vs unpacked) use"); + + NSError *error = nil; + TestPackedExtensions *packedParse = + [TestPackedExtensions parseFromData:unpackedData + extensionRegistry:[UnittestRoot extensionRegistry] + error:&error]; + XCTAssertNotNil(packedParse); + XCTAssertNil(error); + XCTAssertEqualObjects(packedParse, packedOrig); + + error = nil; + TestUnpackedExtensions *unpackedParsed = + [TestUnpackedExtensions parseFromData:packedData + extensionRegistry:[UnittestRoot extensionRegistry] + error:&error]; + XCTAssertNotNil(unpackedParsed); + XCTAssertNil(error); + XCTAssertEqualObjects(unpackedParsed, unpackedOrig); +} + +- (void)testPackedExtensionVsFieldParsing { + // Extensions and fields end up on the wire the same way, so they can parse + // each other. + + TestPackedTypes *fieldsOrig = [TestPackedTypes message]; + TestPackedExtensions *extsOrig = [TestPackedExtensions message]; + [self setPackedFields:fieldsOrig repeatedCount:kGPBDefaultRepeatCount]; + [self setPackedExtensions:extsOrig repeatedCount:kGPBDefaultRepeatCount]; + + NSData *fieldsData = [fieldsOrig data]; + NSData *extsData = [extsOrig data]; + XCTAssertNotNil(fieldsData); + XCTAssertNotNil(extsData); + XCTAssertEqualObjects(fieldsData, extsData); + + NSError *error = nil; + TestPackedTypes *fieldsParse = + [TestPackedTypes parseFromData:extsData error:&error]; + XCTAssertNotNil(fieldsParse); + XCTAssertNil(error); + XCTAssertEqualObjects(fieldsParse, fieldsOrig); + + error = nil; + TestPackedExtensions *extsParse = + [TestPackedExtensions parseFromData:fieldsData + extensionRegistry:[UnittestRoot extensionRegistry] + error:&error]; + XCTAssertNotNil(extsParse); + XCTAssertNil(error); + XCTAssertEqualObjects(extsParse, extsOrig); +} + +- (void)testUnpackedExtensionVsFieldParsing { + // Extensions and fields end up on the wire the same way, so they can parse + // each other. + + TestUnpackedTypes *fieldsOrig = [TestUnpackedTypes message]; + TestUnpackedExtensions *extsOrig = [TestUnpackedExtensions message]; + [self setUnpackedFields:fieldsOrig repeatedCount:3]; + [self setUnpackedExtensions:extsOrig repeatedCount:3]; + + NSData *fieldsData = [fieldsOrig data]; + NSData *extsData = [extsOrig data]; + XCTAssertNotNil(fieldsData); + XCTAssertNotNil(extsData); + XCTAssertEqualObjects(fieldsData, extsData); + + TestUnpackedTypes *fieldsParse = + [TestUnpackedTypes parseFromData:extsData error:NULL]; + XCTAssertNotNil(fieldsParse); + XCTAssertEqualObjects(fieldsParse, fieldsOrig); + + TestUnpackedExtensions *extsParse = + [TestUnpackedExtensions parseFromData:fieldsData + extensionRegistry:[UnittestRoot extensionRegistry] + error:NULL]; + XCTAssertNotNil(extsParse); + XCTAssertEqualObjects(extsParse, extsOrig); +} + #pragma mark - Subset from from map_tests.cc // TEST(GeneratedMapFieldTest, StandardWireFormat) diff --git a/objectivec/Tests/GPBMessageTests.m b/objectivec/Tests/GPBMessageTests.m index e0154c1a..cd0de8fc 100644 --- a/objectivec/Tests/GPBMessageTests.m +++ b/objectivec/Tests/GPBMessageTests.m @@ -35,12 +35,11 @@ #import "GPBArray_PackagePrivate.h" #import "GPBDescriptor.h" #import "GPBDictionary_PackagePrivate.h" -#import "GPBField_PackagePrivate.h" #import "GPBMessage_PackagePrivate.h" +#import "GPBUnknownField_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 @@ -420,10 +419,11 @@ GPBUnknownFieldSet *unknownFields = [[[GPBUnknownFieldSet alloc] init] autorelease]; - GPBField *field = [[[GPBField alloc] initWithNumber:2] autorelease]; + GPBUnknownField *field = + [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; [field addVarint:2]; [unknownFields addField:field]; - field = [[[GPBField alloc] initWithNumber:3] autorelease]; + field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; [field addVarint:4]; [unknownFields addField:field]; @@ -451,7 +451,7 @@ GPBFieldDescriptor *fieldDescriptor = [descriptor fieldWithName:@"defaultInt32"]; XCTAssertNotNil(fieldDescriptor); - GPBValue defaultValue = [fieldDescriptor defaultValue]; + GPBGenericValue defaultValue = [fieldDescriptor defaultValue]; [message setDefaultInt32:defaultValue.valueInt32]; XCTAssertTrue(message.hasDefaultInt32); XCTAssertEqual(message.defaultInt32, defaultValue.valueInt32); @@ -1554,7 +1554,7 @@ // The other should not. TestAllExtensions *message = [TestAllExtensions message]; TestAllExtensions *message2 = [TestAllExtensions message]; - GPBExtensionField *extension = [UnittestRoot optionalGroupExtension]; + GPBExtensionDescriptor *extension = [UnittestRoot optionalGroupExtension]; [message setExtension:extension value:[message2 getExtension:extension]]; XCTAssertEqual([message getExtension:extension], [message2 getExtension:extension]); @@ -1571,9 +1571,9 @@ - (void)testCopyWithAutocreatedExtension { // Mutable copy shouldn't copy autocreated extensions. TestAllExtensions *message = [TestAllExtensions message]; - GPBExtensionField *optionalGroupExtension = + GPBExtensionDescriptor *optionalGroupExtension = [UnittestRoot optionalGroupExtension]; - GPBExtensionField *optionalNestedMessageExtesion = + GPBExtensionDescriptor *optionalNestedMessageExtesion = [UnittestRoot optionalNestedMessageExtension]; TestAllTypes_OptionalGroup *optionalGroup = [message getExtension:optionalGroupExtension]; @@ -1603,7 +1603,7 @@ - (void)testClearMessageAutocreatedExtension { // Call clear should cause it to recreate its autocreated extensions. TestAllExtensions *message = [TestAllExtensions message]; - GPBExtensionField *optionalGroupExtension = + GPBExtensionDescriptor *optionalGroupExtension = [UnittestRoot optionalGroupExtension]; TestAllTypes_OptionalGroup *optionalGroup = [[message getExtension:optionalGroupExtension] retain]; @@ -1620,7 +1620,7 @@ // Should be able to retain autocreated extension while the creator is // dealloced. TestAllExtensions *message = [TestAllExtensions message]; - GPBExtensionField *optionalGroupExtension = + GPBExtensionDescriptor *optionalGroupExtension = [UnittestRoot optionalGroupExtension]; @autoreleasepool { @@ -1638,7 +1638,7 @@ - (void)testClearAutocreatedExtension { // Clearing autocreated extension should NOT cause it to lose its creator. TestAllExtensions *message = [TestAllExtensions message]; - GPBExtensionField *optionalGroupExtension = + GPBExtensionDescriptor *optionalGroupExtension = [UnittestRoot optionalGroupExtension]; TestAllTypes_OptionalGroup *optionalGroup = [[message getExtension:optionalGroupExtension] retain]; @@ -1651,7 +1651,8 @@ // Clearing autocreated extension should not cause its creator to become // visible - GPBExtensionField *recursiveExtension = [UnittestObjcRoot recursiveExtension]; + GPBExtensionDescriptor *recursiveExtension = + [UnittestObjcRoot recursiveExtension]; TestAllExtensions *message_lvl2 = [message getExtension:recursiveExtension]; TestAllExtensions *message_lvl3 = [message_lvl2 getExtension:recursiveExtension]; @@ -1663,7 +1664,8 @@ // 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]; + GPBExtensionDescriptor *recursiveExtension = + [UnittestObjcRoot recursiveExtension]; TestAllExtensions *message_lvl2 = [message getExtension:recursiveExtension]; TestAllExtensions *message_lvl3 = [message_lvl2 getExtension:recursiveExtension]; @@ -1686,7 +1688,7 @@ - (void)testSetAutocreatedExtensionToSelf { // Setting extension to itself should cause it to become visible. TestAllExtensions *message = [TestAllExtensions message]; - GPBExtensionField *optionalGroupExtension = + GPBExtensionDescriptor *optionalGroupExtension = [UnittestRoot optionalGroupExtension]; XCTAssertNotNil([message getExtension:optionalGroupExtension]); XCTAssertFalse([message hasExtension:optionalGroupExtension]); @@ -1696,7 +1698,8 @@ } - (void)testAutocreatedExtensionMemoryLeaks { - GPBExtensionField *recursiveExtension = [UnittestObjcRoot recursiveExtension]; + GPBExtensionDescriptor *recursiveExtension = + [UnittestObjcRoot recursiveExtension]; // Test for memory leaks with autocreated extensions. TestAllExtensions *message; @@ -1729,7 +1732,8 @@ } - (void)testSetExtensionWithAutocreatedValue { - GPBExtensionField *recursiveExtension = [UnittestObjcRoot recursiveExtension]; + GPBExtensionDescriptor *recursiveExtension = + [UnittestObjcRoot recursiveExtension]; TestAllExtensions *message; @autoreleasepool { @@ -1814,9 +1818,9 @@ } - (void)testEnumDescriptorFromExtensionDescriptor { - GPBExtensionField *extField = [UnittestRoot optionalForeignEnumExtension]; - GPBExtensionDescriptor *extDescriptor = extField.descriptor; - XCTAssertEqual(extDescriptor.type, GPBTypeEnum); + GPBExtensionDescriptor *extDescriptor = + [UnittestRoot optionalForeignEnumExtension]; + XCTAssertEqual(extDescriptor.dataType, GPBDataTypeEnum); GPBEnumDescriptor *enumDescriptor = extDescriptor.enumDescriptor; GPBEnumDescriptor *expectedDescriptor = ForeignEnum_EnumDescriptor(); XCTAssertEqualObjects(enumDescriptor, expectedDescriptor); @@ -1925,11 +1929,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/GPBSwiftTests.swift b/objectivec/Tests/GPBSwiftTests.swift index 30b9cbd4..5fbe74fd 100644 --- a/objectivec/Tests/GPBSwiftTests.swift +++ b/objectivec/Tests/GPBSwiftTests.swift @@ -446,7 +446,7 @@ class GPBBridgeTests: XCTestCase { let data = msg.data() - let msg2 = Message2(data: data, error:nil) + let msg2 = Message2(data: data!, error:nil) XCTAssertTrue(msg2 !== msg) // New instance XCTAssertEqual(msg.optionalInt32, Int32(100)) XCTAssertEqual(msg.optionalInt64, Int64(101)) diff --git a/objectivec/Tests/GPBTestUtilities.h b/objectivec/Tests/GPBTestUtilities.h index 6ae68c3a..44c80844 100644 --- a/objectivec/Tests/GPBTestUtilities.h +++ b/objectivec/Tests/GPBTestUtilities.h @@ -35,6 +35,8 @@ @class TestMap; @class TestPackedTypes; @class TestPackedExtensions; +@class TestUnpackedTypes; +@class TestUnpackedExtensions; @class GPBExtensionRegistry; @@ -55,8 +57,12 @@ extern const uint32_t kGPBDefaultRepeatCount; repeatedCount:(uint32_t)count; - (void)setPackedFields:(TestPackedTypes *)message repeatedCount:(uint32_t)count; +- (void)setUnpackedFields:(TestUnpackedTypes *)message + repeatedCount:(uint32_t)count; - (void)setPackedExtensions:(TestPackedExtensions *)message repeatedCount:(uint32_t)count; +- (void)setUnpackedExtensions:(TestUnpackedExtensions *)message + repeatedCount:(uint32_t)count; - (void)setAllMapFields:(TestMap *)message numEntries:(uint32_t)count; - (TestAllTypes *)allSetRepeatedCount:(uint32_t)count; diff --git a/objectivec/Tests/GPBTestUtilities.m b/objectivec/Tests/GPBTestUtilities.m index 6058dfc1..3d85c744 100644 --- a/objectivec/Tests/GPBTestUtilities.m +++ b/objectivec/Tests/GPBTestUtilities.m @@ -599,6 +599,33 @@ const uint32_t kGPBDefaultRepeatCount = 2; XCTAssertEqual(count, message.repeatedStringPieceArray.count); XCTAssertEqual(count, message.repeatedCordArray.count); + 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]); @@ -1097,6 +1124,72 @@ const uint32_t kGPBDefaultRepeatCount = 2; } } +- (void)setAllTestPackedFields:(TestPackedTypes *)message { + // Must match -setAllTestUnpackedFields: + [message.packedInt32Array addValue:101]; + [message.packedInt64Array addValue:102]; + [message.packedUint32Array addValue:103]; + [message.packedUint64Array addValue:104]; + [message.packedSint32Array addValue:105]; + [message.packedSint64Array addValue:106]; + [message.packedFixed32Array addValue:107]; + [message.packedFixed64Array addValue:108]; + [message.packedSfixed32Array addValue:109]; + [message.packedSfixed64Array addValue:110]; + [message.packedFloatArray addValue:111.f]; + [message.packedDoubleArray addValue:112.]; + [message.packedBoolArray addValue:YES]; + [message.packedEnumArray addValue:ForeignEnum_ForeignBar]; + + [message.packedInt32Array addValue:201]; + [message.packedInt64Array addValue:302]; + [message.packedUint32Array addValue:203]; + [message.packedUint64Array addValue:204]; + [message.packedSint32Array addValue:205]; + [message.packedSint64Array addValue:206]; + [message.packedFixed32Array addValue:207]; + [message.packedFixed64Array addValue:208]; + [message.packedSfixed32Array addValue:209]; + [message.packedSfixed64Array addValue:210]; + [message.packedFloatArray addValue:211.f]; + [message.packedDoubleArray addValue:212.]; + [message.packedBoolArray addValue:NO]; + [message.packedEnumArray addValue:ForeignEnum_ForeignBaz]; +} + +- (void)setAllTestUnpackedFields:(TestUnpackedTypes *)message { + // Must match -setAllTestPackedFields: + [message.unpackedInt32Array addValue:101]; + [message.unpackedInt64Array addValue:102]; + [message.unpackedUint32Array addValue:103]; + [message.unpackedUint64Array addValue:104]; + [message.unpackedSint32Array addValue:105]; + [message.unpackedSint64Array addValue:106]; + [message.unpackedFixed32Array addValue:107]; + [message.unpackedFixed64Array addValue:108]; + [message.unpackedSfixed32Array addValue:109]; + [message.unpackedSfixed64Array addValue:110]; + [message.unpackedFloatArray addValue:111.f]; + [message.unpackedDoubleArray addValue:112.]; + [message.unpackedBoolArray addValue:YES]; + [message.unpackedEnumArray addValue:ForeignEnum_ForeignBar]; + + [message.unpackedInt32Array addValue:201]; + [message.unpackedInt64Array addValue:302]; + [message.unpackedUint32Array addValue:203]; + [message.unpackedUint64Array addValue:204]; + [message.unpackedSint32Array addValue:205]; + [message.unpackedSint64Array addValue:206]; + [message.unpackedFixed32Array addValue:207]; + [message.unpackedFixed64Array addValue:208]; + [message.unpackedSfixed32Array addValue:209]; + [message.unpackedSfixed64Array addValue:210]; + [message.unpackedFloatArray addValue:211.f]; + [message.unpackedDoubleArray addValue:212.]; + [message.unpackedBoolArray addValue:NO]; + [message.unpackedEnumArray addValue:ForeignEnum_ForeignBaz]; +} + - (GPBExtensionRegistry *)extensionRegistry { return [UnittestRoot extensionRegistry]; } @@ -1189,6 +1282,7 @@ const uint32_t kGPBDefaultRepeatCount = 2; XCTAssertEqualObjects(message.optionalCord, @""); // Repeated fields are empty. + XCTAssertEqual(0U, message.repeatedInt32Array.count); XCTAssertEqual(0U, message.repeatedInt64Array.count); XCTAssertEqual(0U, message.repeatedUint32Array.count); @@ -1216,6 +1310,33 @@ const uint32_t kGPBDefaultRepeatCount = 2; XCTAssertEqual(0U, message.repeatedStringPieceArray.count); XCTAssertEqual(0U, message.repeatedCordArray.count); + 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); @@ -1474,6 +1595,7 @@ const uint32_t kGPBDefaultRepeatCount = 2; // 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); @@ -1501,6 +1623,33 @@ const uint32_t kGPBDefaultRepeatCount = 2; XCTAssertEqual(count, message.repeatedStringPieceArray.count); XCTAssertEqual(count, message.repeatedCordArray.count); + 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]); @@ -1563,105 +1712,101 @@ const uint32_t kGPBDefaultRepeatCount = 2; - (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]; + // Must match -setUnpackedFields:repeatedCount: + // Must match -setPackedExtensions:repeatedCount: + // Must match -setUnpackedExtensions:repeatedCount: + for (uint32_t i = 0; i < count; ++i) { + [message.packedInt32Array addValue:601 + i * 100]; } - { - GPBInt64Array *scratch = [GPBInt64Array array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:602 + i * 100]; - } - [message setPackedInt64Array:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedInt64Array addValue:602 + i * 100]; } - { - GPBUInt32Array *scratch = [GPBUInt32Array array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:603 + i * 100]; - } - [message setPackedUint32Array:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedUint32Array addValue:603 + i * 100]; } - { - GPBUInt64Array *scratch = [GPBUInt64Array array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:604 + i * 100]; - } - [message setPackedUint64Array:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedUint64Array addValue:604 + i * 100]; } - { - GPBInt32Array *scratch = [GPBInt32Array array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:605 + i * 100]; - } - [message setPackedSint32Array:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedSint32Array addValue:605 + i * 100]; } - { - GPBInt64Array *scratch = [GPBInt64Array array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:606 + i * 100]; - } - [message setPackedSint64Array:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedSint64Array addValue:606 + i * 100]; } - { - GPBUInt32Array *scratch = [GPBUInt32Array array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:607 + i * 100]; - } - [message setPackedFixed32Array:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedFixed32Array addValue:607 + i * 100]; } - { - GPBUInt64Array *scratch = [GPBUInt64Array array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:608 + i * 100]; - } - [message setPackedFixed64Array:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedFixed64Array addValue:608 + i * 100]; } - { - GPBInt32Array *scratch = [GPBInt32Array array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:609 + i * 100]; - } - [message setPackedSfixed32Array:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedSfixed32Array addValue:609 + i * 100]; } - { - GPBInt64Array *scratch = [GPBInt64Array array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:610 + i * 100]; - } - [message setPackedSfixed64Array:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedSfixed64Array addValue:610 + i * 100]; } - { - GPBFloatArray *scratch = [GPBFloatArray array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:611 + i * 100]; - } - [message setPackedFloatArray:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedFloatArray addValue:611 + i * 100]; } - { - GPBDoubleArray *scratch = [GPBDoubleArray array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:612 + i * 100]; - } - [message setPackedDoubleArray:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedDoubleArray addValue:612 + i * 100]; } - { - GPBBoolArray *scratch = [GPBBoolArray array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:(i % 2) ? YES : NO]; - } - [message setPackedBoolArray:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedBoolArray addValue:(i % 2) ? YES : NO]; } - { - 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]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedEnumArray + addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz]; + } +} + +- (void)setUnpackedFields:(TestUnpackedTypes *)message + repeatedCount:(uint32_t)count { + // Must match -setPackedFields:repeatedCount: + // Must match -setPackedExtensions:repeatedCount: + // Must match -setUnpackedExtensions:repeatedCount: + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedInt32Array addValue:601 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedInt64Array addValue:602 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedUint32Array addValue:603 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedUint64Array addValue:604 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedSint32Array addValue:605 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedSint64Array addValue:606 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedFixed32Array addValue:607 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedFixed64Array addValue:608 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedSfixed32Array addValue:609 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedSfixed64Array addValue:610 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedFloatArray addValue:611 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedDoubleArray addValue:612 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedBoolArray addValue:(i % 2) ? YES : NO]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedEnumArray + addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz]; } } @@ -1708,6 +1853,9 @@ const uint32_t kGPBDefaultRepeatCount = 2; - (void)setPackedExtensions:(TestPackedExtensions *)message repeatedCount:(uint32_t)count { + // Must match -setPackedFields:repeatedCount: + // Must match -setUnpackedFields:repeatedCount: + // Must match -setUnpackedExtensions:repeatedCount: for (uint32_t i = 0; i < count; i++) { [message addExtension:[UnittestRoot packedInt32Extension] value:@(601 + i * 100)]; @@ -1741,6 +1889,44 @@ const uint32_t kGPBDefaultRepeatCount = 2; } } +- (void)setUnpackedExtensions:(TestUnpackedExtensions *)message + repeatedCount:(uint32_t)count { + // Must match -setPackedFields:repeatedCount: + // Must match -setUnpackedFields:repeatedCount: + // Must match -setPackedExtensions:repeatedCount: + for (uint32_t i = 0; i < count; i++) { + [message addExtension:[UnittestRoot unpackedInt32Extension] + value:@(601 + i * 100)]; + [message addExtension:[UnittestRoot unpackedInt64Extension] + value:@(602 + i * 100)]; + [message addExtension:[UnittestRoot unpackedUint32Extension] + value:@(603 + i * 100)]; + [message addExtension:[UnittestRoot unpackedUint64Extension] + value:@(604 + i * 100)]; + [message addExtension:[UnittestRoot unpackedSint32Extension] + value:@(605 + i * 100)]; + [message addExtension:[UnittestRoot unpackedSint64Extension] + value:@(606 + i * 100)]; + [message addExtension:[UnittestRoot unpackedFixed32Extension] + value:@(607 + i * 100)]; + [message addExtension:[UnittestRoot unpackedFixed64Extension] + value:@(608 + i * 100)]; + [message addExtension:[UnittestRoot unpackedSfixed32Extension] + value:@(609 + i * 100)]; + [message addExtension:[UnittestRoot unpackedSfixed64Extension] + value:@(610 + i * 100)]; + [message addExtension:[UnittestRoot unpackedFloatExtension] + value:@(611 + i * 100)]; + [message addExtension:[UnittestRoot unpackedDoubleExtension] + value:@(612 + i * 100)]; + [message addExtension:[UnittestRoot unpackedBoolExtension] + value:@((i % 2) ? YES : NO)]; + [message addExtension:[UnittestRoot unpackedEnumExtension] + value:@((i % 2) ? ForeignEnum_ForeignBar + : ForeignEnum_ForeignBaz)]; + } +} + - (void)assertPackedExtensionsSet:(TestPackedExtensions *)message repeatedCount:(uint32_t)count{ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedInt32Extension]] count]); @@ -1884,6 +2070,34 @@ const uint32_t kGPBDefaultRepeatCount = 2; XCTAssertEqualObjects(message.repeatedStringPieceArray, [message valueForKey:@"repeatedStringPieceArray"]); XCTAssertEqualObjects(message.repeatedCordArray, [message valueForKey:@"repeatedCordArray"]); + XCTAssertEqualObjects(@(message.repeatedInt32Array_Count), [message valueForKey:@"repeatedInt32Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedInt64Array_Count), [message valueForKey:@"repeatedInt64Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedUint32Array_Count), [message valueForKey:@"repeatedUint32Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedUint64Array_Count), [message valueForKey:@"repeatedUint64Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedSint32Array_Count), [message valueForKey:@"repeatedSint32Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedSint64Array_Count), [message valueForKey:@"repeatedSint64Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedFixed32Array_Count), [message valueForKey:@"repeatedFixed32Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedFixed64Array_Count), [message valueForKey:@"repeatedFixed64Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedSfixed32Array_Count), [message valueForKey:@"repeatedSfixed32Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedSfixed64Array_Count), [message valueForKey:@"repeatedSfixed64Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedFloatArray_Count), [message valueForKey:@"repeatedFloatArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedDoubleArray_Count), [message valueForKey:@"repeatedDoubleArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedBoolArray_Count), [message valueForKey:@"repeatedBoolArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedStringArray_Count), [message valueForKey:@"repeatedStringArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedBytesArray_Count), [message valueForKey:@"repeatedBytesArray_Count"]); + + XCTAssertEqualObjects(@(message.repeatedGroupArray_Count), [message valueForKey:@"repeatedGroupArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedNestedMessageArray_Count), [message valueForKey:@"repeatedNestedMessageArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedForeignMessageArray_Count), [message valueForKey:@"repeatedForeignMessageArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedImportMessageArray_Count), [message valueForKey:@"repeatedImportMessageArray_Count"]); + + XCTAssertEqualObjects(@(message.repeatedNestedEnumArray_Count), [message valueForKey:@"repeatedNestedEnumArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedForeignEnumArray_Count), [message valueForKey:@"repeatedForeignEnumArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedImportEnumArray_Count), [message valueForKey:@"repeatedImportEnumArray_Count"]); + + XCTAssertEqualObjects(@(message.repeatedStringPieceArray_Count), [message valueForKey:@"repeatedStringPieceArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedCordArray_Count), [message valueForKey:@"repeatedCordArray_Count"]); + // ----------------------------------------------------------------- XCTAssertEqualObjects([message valueForKey:@"hasDefaultInt32"], @YES); diff --git a/objectivec/Tests/GPBUnittestProtos.m b/objectivec/Tests/GPBUnittestProtos.m index 2c271bf7..0a3fc583 100644 --- a/objectivec/Tests/GPBUnittestProtos.m +++ b/objectivec/Tests/GPBUnittestProtos.m @@ -40,16 +40,15 @@ #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/UnittestObjcStartup.pbobjc.m" #import "google/protobuf/UnittestOptimizeFor.pbobjc.m" #import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.m" #import "google/protobuf/UnittestRuntimeProto2.pbobjc.m" diff --git a/objectivec/Tests/GPBUnknownFieldSetTest.m b/objectivec/Tests/GPBUnknownFieldSetTest.m index 491bba9e..01217ca6 100644 --- a/objectivec/Tests/GPBUnknownFieldSetTest.m +++ b/objectivec/Tests/GPBUnknownFieldSetTest.m @@ -30,7 +30,7 @@ #import "GPBTestUtilities.h" -#import "GPBField_PackagePrivate.h" +#import "GPBUnknownField_PackagePrivate.h" #import "GPBUnknownFieldSet_PackagePrivate.h" #import "google/protobuf/Unittest.pbobjc.h" @@ -60,7 +60,7 @@ unknownFields_ = emptyMessage_.unknownFields; } -- (GPBField*)getField:(int32_t)number { +- (GPBUnknownField *)getField:(int32_t)number { return [unknownFields_ getField:number]; } @@ -75,17 +75,17 @@ [unknownFields_ getTags:tags]; for (NSUInteger i = 0; i < count; ++i) { int32_t tag = tags[i]; - GPBField* field = [unknownFields_ getField:tag]; + GPBUnknownField* 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]; + GPBUnknownField* varintField = + [[[GPBUnknownField 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]; + GPBUnknownField* fixed32Field = + [[[GPBUnknownField alloc] initWithNumber:tag] autorelease]; [fixed32Field addFixed32:1]; [bizarroFields addField:fixed32Field]; } @@ -110,34 +110,34 @@ - (void)testMergeFrom { GPBUnknownFieldSet* set1 = [[[GPBUnknownFieldSet alloc] init] autorelease]; - GPBField* field = [[[GPBField alloc] initWithNumber:2] autorelease]; + GPBUnknownField* field = [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; [field addVarint:2]; [set1 addField:field]; - field = [[[GPBField alloc] initWithNumber:3] autorelease]; + field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; [field addVarint:4]; [set1 addField:field]; GPBUnknownFieldSet* set2 = [[[GPBUnknownFieldSet alloc] init] autorelease]; - field = [[[GPBField alloc] initWithNumber:1] autorelease]; + field = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; [field addVarint:1]; [set2 addField:field]; - field = [[[GPBField alloc] initWithNumber:3] autorelease]; + field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; [field addVarint:3]; [set2 addField:field]; GPBUnknownFieldSet* set3 = [[[GPBUnknownFieldSet alloc] init] autorelease]; - field = [[[GPBField alloc] initWithNumber:1] autorelease]; + field = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; [field addVarint:1]; [set3 addField:field]; - field = [[[GPBField alloc] initWithNumber:3] autorelease]; + field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; [field addVarint:4]; [set3 addField:field]; GPBUnknownFieldSet* set4 = [[[GPBUnknownFieldSet alloc] init] autorelease]; - field = [[[GPBField alloc] initWithNumber:2] autorelease]; + field = [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; [field addVarint:2]; [set4 addField:field]; - field = [[[GPBField alloc] initWithNumber:3] autorelease]; + field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; [field addVarint:3]; [set4 addField:field]; @@ -162,7 +162,7 @@ } - (void)testClearMessage { - TestEmptyMessage* message = [TestEmptyMessage message]; + TestEmptyMessage *message = [TestEmptyMessage message]; [message mergeFrom:emptyMessage_]; [message clear]; XCTAssertEqual(message.serializedSize, (size_t)0); @@ -170,8 +170,9 @@ - (void)testParseKnownAndUnknown { // Test mixing known and unknown fields when parsing. - GPBUnknownFieldSet* fields = [[unknownFields_ copy] autorelease]; - GPBField* field = [[[GPBField alloc] initWithNumber:123456] autorelease]; + GPBUnknownFieldSet *fields = [[unknownFields_ copy] autorelease]; + GPBUnknownField *field = + [[[GPBUnknownField alloc] initWithNumber:123456] autorelease]; [field addVarint:654321]; [fields addField:field]; @@ -181,7 +182,7 @@ [self assertAllFieldsSet:destination repeatedCount:kGPBDefaultRepeatCount]; XCTAssertEqual(destination.unknownFields.countOfFields, (NSUInteger)1); - GPBField* field2 = [destination.unknownFields getField:123456]; + GPBUnknownField* field2 = [destination.unknownFields getField:123456]; XCTAssertEqual(field2.varintList.count, (NSUInteger)1); XCTAssertEqual(654321ULL, [field2.varintList valueAtIndex:0]); } @@ -230,7 +231,7 @@ - (void)testLargeVarint { GPBUnknownFieldSet* fields = [[unknownFields_ copy] autorelease]; - GPBField* field = [[[GPBField alloc] initWithNumber:1] autorelease]; + GPBUnknownField* field = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; [field addVarint:0x7FFFFFFFFFFFFFFFL]; [fields addField:field]; @@ -238,19 +239,19 @@ GPBUnknownFieldSet* parsed = [[[GPBUnknownFieldSet alloc] init] autorelease]; [parsed mergeFromData:data]; - GPBField* field2 = [parsed getField:1]; + GPBUnknownField* 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]; + GPBUnknownField* field1 = [[[GPBUnknownField 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]; + GPBUnknownField* field2 = [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; [field2 mergeFromField:field1]; XCTAssertEqualObjects(field1, field2); } diff --git a/objectivec/Tests/GPBUtilitiesTests.m b/objectivec/Tests/GPBUtilitiesTests.m index 02de0197..ba1fc270 100644 --- a/objectivec/Tests/GPBUtilitiesTests.m +++ b/objectivec/Tests/GPBUtilitiesTests.m @@ -47,141 +47,6 @@ @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 { @@ -194,61 +59,6 @@ TEST_APPLY_FUNCTIONS_FUNC(Object) 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, diff --git a/objectivec/Tests/GPBWireFormatTests.m b/objectivec/Tests/GPBWireFormatTests.m index fc5c4bda..d722d7b2 100644 --- a/objectivec/Tests/GPBWireFormatTests.m +++ b/objectivec/Tests/GPBWireFormatTests.m @@ -32,7 +32,7 @@ #import "GPBCodedInputStream.h" #import "GPBMessage_PackagePrivate.h" -#import "GPBField_PackagePrivate.h" +#import "GPBUnknownField_PackagePrivate.h" #import "google/protobuf/Unittest.pbobjc.h" #import "google/protobuf/UnittestMset.pbobjc.h" @@ -143,8 +143,8 @@ const int kUnknownTypeId = 1550055; setI:123]; [[message_set getExtension:[TestMessageSetExtension2 messageSetExtension]] setStr:@"foo"]; - GPBField* unknownField = - [[[GPBField alloc] initWithNumber:kUnknownTypeId] autorelease]; + GPBUnknownField* unknownField = + [[[GPBUnknownField alloc] initWithNumber:kUnknownTypeId] autorelease]; [unknownField addLengthDelimited:[NSData dataWithBytes:"bar" length:3]]; GPBUnknownFieldSet* unknownFieldSet = [[[GPBUnknownFieldSet alloc] init] autorelease]; @@ -159,9 +159,9 @@ const int kUnknownTypeId = 1550055; XCTAssertEqual([raw.unknownFields countOfFields], (NSUInteger)0); XCTAssertEqual(raw.itemArray.count, (NSUInteger)3); - XCTAssertEqual([raw.itemArray[0] typeId], + XCTAssertEqual((uint32_t)[raw.itemArray[0] typeId], [TestMessageSetExtension1 messageSetExtension].fieldNumber); - XCTAssertEqual([raw.itemArray[1] typeId], + XCTAssertEqual((uint32_t)[raw.itemArray[1] typeId], [TestMessageSetExtension2 messageSetExtension].fieldNumber); XCTAssertEqual([raw.itemArray[2] typeId], kUnknownTypeId); @@ -227,7 +227,7 @@ const int kUnknownTypeId = 1550055; @"foo"); XCTAssertEqual([messageSet.unknownFields countOfFields], (NSUInteger)1); - GPBField* unknownField = [messageSet.unknownFields getField:kUnknownTypeId]; + GPBUnknownField* unknownField = [messageSet.unknownFields getField:kUnknownTypeId]; XCTAssertNotNil(unknownField); XCTAssertEqual(unknownField.lengthDelimitedList.count, (NSUInteger)1); XCTAssertEqualObjects(unknownField.lengthDelimitedList[0], diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json index ecd3584e..0cbf9acc 100644 --- a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json @@ -34,19 +34,19 @@ { "size" : "57x57", "idiom" : "iphone", - "filename" : "iPhone6@2x.png", + "filename" : "iPhone6_2x.png", "scale" : "2x" }, { "size" : "60x60", "idiom" : "iphone", - "filename" : "iPhone7@2x.png", + "filename" : "iPhone7_2x.png", "scale" : "2x" }, { "size" : "60x60", "idiom" : "iphone", - "filename" : "iPhone7@3x.png", + "filename" : "iPhone7_3x.png", "scale" : "3x" }, { @@ -88,7 +88,7 @@ { "size" : "72x72", "idiom" : "ipad", - "filename" : "iPad6@2x.png", + "filename" : "iPad6_2x.png", "scale" : "2x" }, { @@ -100,7 +100,7 @@ { "size" : "76x76", "idiom" : "ipad", - "filename" : "iPad7@2x.png", + "filename" : "iPad7_2x.png", "scale" : "2x" }, { @@ -113,4 +113,4 @@ "version" : 1, "author" : "xcode" } -}
\ No newline at end of file +} diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6@2x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6_2x.png Binary files differindex 2ec93704..2ec93704 100644 --- a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6@2x.png +++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6_2x.png diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7@2x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7_2x.png Binary files differindex e39cc3e7..e39cc3e7 100644 --- a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7@2x.png +++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7_2x.png diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6@2x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6_2x.png Binary files differindex 2424997f..2424997f 100644 --- a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6@2x.png +++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6_2x.png diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@2x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_2x.png Binary files differindex 10bfc3cf..10bfc3cf 100644 --- a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@2x.png +++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_2x.png diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@3x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_3x.png Binary files differindex 8d16f14d..8d16f14d 100644 --- a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@3x.png +++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_3x.png diff --git a/objectivec/Tests/unittest_name_mangling.proto b/objectivec/Tests/unittest_objc_startup.proto index aadad6d6..aee7bd55 100644 --- a/objectivec/Tests/unittest_name_mangling.proto +++ b/objectivec/Tests/unittest_objc_startup.proto @@ -1,5 +1,6 @@ // Protocol Buffers - Google's data interchange format -// Copyright 2015 Google Inc. All rights reserved. +// 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 @@ -29,9 +30,20 @@ syntax = "proto2"; -option objc_class_prefix = "ABC"; +package protobuf_objc_unittest; -package protobuf_unittest; +message TestObjCStartupMessage { + extensions 1 to max; +} -// TODO(thomasvl): Add tests for the special cases in name mangling. +extend TestObjCStartupMessage { + // Singular + optional int32 optional_int32_extension = 1; + repeated int32 repeated_int32_extension = 2; +} +message TestObjCStartupNested { + extend TestObjCStartupMessage { + optional string nested_string_extension = 3; + } +} diff --git a/objectivec/google/protobuf/Any.pbobjc.h b/objectivec/google/protobuf/Any.pbobjc.h index 8154318e..e09f3a49 100644 --- a/objectivec/google/protobuf/Any.pbobjc.h +++ b/objectivec/google/protobuf/Any.pbobjc.h @@ -11,6 +11,7 @@ CF_EXTERN_C_BEGIN +NS_ASSUME_NONNULL_BEGIN #pragma mark - GPBAnyRoot @@ -88,13 +89,15 @@ typedef GPB_ENUM(GPBAny_FieldNumber) { // 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). -@property(nonatomic, readwrite, copy) NSString *typeURL; +@property(nonatomic, readwrite, copy, null_resettable) NSString *typeURL; // Must be valid serialized data of the above specified type. -@property(nonatomic, readwrite, copy) NSData *value; +@property(nonatomic, readwrite, copy, null_resettable) NSData *value; @end +NS_ASSUME_NONNULL_END + CF_EXTERN_C_END // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Any.pbobjc.m b/objectivec/google/protobuf/Any.pbobjc.m index 4db73cb9..b41102a4 100644 --- a/objectivec/google/protobuf/Any.pbobjc.m +++ b/objectivec/google/protobuf/Any.pbobjc.m @@ -11,11 +11,14 @@ @end +#pragma mark - GPBAnyRoot_FileDescriptor + static GPBFileDescriptor *GPBAnyRoot_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) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -29,16 +32,16 @@ static GPBFileDescriptor *GPBAnyRoot_FileDescriptor(void) { @dynamic typeURL; @dynamic value; -typedef struct GPBAny_Storage { +typedef struct GPBAny__storage_ { uint32_t _has_storage_[1]; NSString *typeURL; NSData *value; -} GPBAny_Storage; +} GPBAny__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -46,10 +49,10 @@ typedef struct GPBAny_Storage { .number = GPBAny_FieldNumber_TypeURL, .hasIndex = 0, .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom, - .type = GPBTypeString, - .offset = offsetof(GPBAny_Storage, typeURL), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBAny__storage_, typeURL), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -57,10 +60,10 @@ typedef struct GPBAny_Storage { .number = GPBAny_FieldNumber_Value, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeData, - .offset = offsetof(GPBAny_Storage, value), + .dataType = GPBDataTypeBytes, + .offset = offsetof(GPBAny__storage_, value), .defaultValue.valueData = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; @@ -69,20 +72,23 @@ typedef struct GPBAny_Storage { #else static const char *extraTextFormatInfo = "\001\001\004\241!!\000"; #endif // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBAny class] - rootClass:[GPBAnyRoot class] - file:GPBAnyRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBAny_Storage) - wireFormat:NO - extraTextFormatInfo:extraTextFormatInfo]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBAny class] + rootClass:[GPBAnyRoot class] + file:GPBAnyRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBAny__storage_) + wireFormat:NO + extraTextFormatInfo:extraTextFormatInfo]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/Api.pbobjc.h b/objectivec/google/protobuf/Api.pbobjc.h index 9e6fc850..021dac5f 100644 --- a/objectivec/google/protobuf/Api.pbobjc.h +++ b/objectivec/google/protobuf/Api.pbobjc.h @@ -13,6 +13,7 @@ CF_EXTERN_C_BEGIN @class GPBSourceContext; +NS_ASSUME_NONNULL_BEGIN #pragma mark - GPBApiRoot @@ -40,15 +41,17 @@ typedef GPB_ENUM(GPBApi_FieldNumber) { // The fully qualified name of this api, including package name // followed by the api's simple name. -@property(nonatomic, readwrite, copy) NSString *name; +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; // The methods of this api, in unspecified order. // |methodsArray| contains |GPBMethod| -@property(nonatomic, readwrite, strong) NSMutableArray *methodsArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *methodsArray; +@property(nonatomic, readonly) NSUInteger methodsArray_Count; // Any metadata attached to the API. // |optionsArray| contains |GPBOption| -@property(nonatomic, readwrite, strong) NSMutableArray *optionsArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +@property(nonatomic, readonly) NSUInteger optionsArray_Count; // A version string for this api. If specified, must have the form // `major-version.minor-version`, as in `1.10`. If the minor version @@ -72,12 +75,12 @@ typedef GPB_ENUM(GPBApi_FieldNumber) { // experimental, none-GA apis. // // See also: [design doc](http://go/api-versioning). -@property(nonatomic, readwrite, copy) NSString *version; +@property(nonatomic, readwrite, copy, null_resettable) NSString *version; // Source context for the protocol buffer service represented by this // message. @property(nonatomic, readwrite) BOOL hasSourceContext; -@property(nonatomic, readwrite, strong) GPBSourceContext *sourceContext; +@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext; @end @@ -96,26 +99,29 @@ typedef GPB_ENUM(GPBMethod_FieldNumber) { @interface GPBMethod : GPBMessage // The simple name of this method. -@property(nonatomic, readwrite, copy) NSString *name; +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; // A URL of the input message type. -@property(nonatomic, readwrite, copy) NSString *requestTypeURL; +@property(nonatomic, readwrite, copy, null_resettable) NSString *requestTypeURL; // If true, the request is streamed. @property(nonatomic, readwrite) BOOL requestStreaming; // The URL of the output message type. -@property(nonatomic, readwrite, copy) NSString *responseTypeURL; +@property(nonatomic, readwrite, copy, null_resettable) NSString *responseTypeURL; // If true, the response is streamed. @property(nonatomic, readwrite) BOOL responseStreaming; // Any metadata attached to the method. // |optionsArray| contains |GPBOption| -@property(nonatomic, readwrite, strong) NSMutableArray *optionsArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +@property(nonatomic, readonly) NSUInteger optionsArray_Count; @end +NS_ASSUME_NONNULL_END + CF_EXTERN_C_END // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Api.pbobjc.m b/objectivec/google/protobuf/Api.pbobjc.m index 9416860a..c2be94ab 100644 --- a/objectivec/google/protobuf/Api.pbobjc.m +++ b/objectivec/google/protobuf/Api.pbobjc.m @@ -16,10 +16,8 @@ // about thread safety and initialization of registry. static GPBExtensionRegistry* registry = nil; if (!registry) { + GPBDebugCheckRuntimeVersion(); registry = [[GPBExtensionRegistry alloc] init]; - static GPBExtensionDescription descriptions[] = { - }; - #pragma unused (descriptions) [registry addExtensions:[GPBSourceContextRoot extensionRegistry]]; [registry addExtensions:[GPBTypeRoot extensionRegistry]]; } @@ -28,11 +26,14 @@ @end +#pragma mark - GPBApiRoot_FileDescriptor + static GPBFileDescriptor *GPBApiRoot_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) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -44,24 +45,24 @@ static GPBFileDescriptor *GPBApiRoot_FileDescriptor(void) { @implementation GPBApi @dynamic name; -@dynamic methodsArray; -@dynamic optionsArray; +@dynamic methodsArray, methodsArray_Count; +@dynamic optionsArray, optionsArray_Count; @dynamic version; @dynamic hasSourceContext, sourceContext; -typedef struct GPBApi_Storage { +typedef struct GPBApi__storage_ { uint32_t _has_storage_[1]; NSString *name; NSMutableArray *methodsArray; NSMutableArray *optionsArray; NSString *version; GPBSourceContext *sourceContext; -} GPBApi_Storage; +} GPBApi__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -69,10 +70,10 @@ typedef struct GPBApi_Storage { .number = GPBApi_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBApi_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBApi__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -80,10 +81,10 @@ typedef struct GPBApi_Storage { .number = GPBApi_FieldNumber_MethodsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBApi_Storage, methodsArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBApi__storage_, methodsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBMethod), + .dataTypeSpecific.className = GPBStringifySymbol(GPBMethod), .fieldOptions = NULL, }, { @@ -91,10 +92,10 @@ typedef struct GPBApi_Storage { .number = GPBApi_FieldNumber_OptionsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBApi_Storage, optionsArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBApi__storage_, optionsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), .fieldOptions = NULL, }, { @@ -102,10 +103,10 @@ typedef struct GPBApi_Storage { .number = GPBApi_FieldNumber_Version, .hasIndex = 3, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBApi_Storage, version), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBApi__storage_, version), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -113,26 +114,29 @@ typedef struct GPBApi_Storage { .number = GPBApi_FieldNumber_SourceContext, .hasIndex = 4, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBApi_Storage, sourceContext), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBApi__storage_, sourceContext), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBSourceContext), + .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBApi class] - rootClass:[GPBApiRoot class] - file:GPBApiRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBApi_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBApi class] + rootClass:[GPBApiRoot class] + file:GPBApiRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBApi__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -148,9 +152,9 @@ typedef struct GPBApi_Storage { @dynamic requestStreaming; @dynamic responseTypeURL; @dynamic responseStreaming; -@dynamic optionsArray; +@dynamic optionsArray, optionsArray_Count; -typedef struct GPBMethod_Storage { +typedef struct GPBMethod__storage_ { uint32_t _has_storage_[1]; BOOL requestStreaming; BOOL responseStreaming; @@ -158,12 +162,12 @@ typedef struct GPBMethod_Storage { NSString *requestTypeURL; NSString *responseTypeURL; NSMutableArray *optionsArray; -} GPBMethod_Storage; +} GPBMethod__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -171,10 +175,10 @@ typedef struct GPBMethod_Storage { .number = GPBMethod_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBMethod_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBMethod__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -182,10 +186,10 @@ typedef struct GPBMethod_Storage { .number = GPBMethod_FieldNumber_RequestTypeURL, .hasIndex = 1, .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom, - .type = GPBTypeString, - .offset = offsetof(GPBMethod_Storage, requestTypeURL), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBMethod__storage_, requestTypeURL), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -193,10 +197,10 @@ typedef struct GPBMethod_Storage { .number = GPBMethod_FieldNumber_RequestStreaming, .hasIndex = 2, .flags = GPBFieldOptional, - .type = GPBTypeBool, - .offset = offsetof(GPBMethod_Storage, requestStreaming), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBMethod__storage_, requestStreaming), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -204,10 +208,10 @@ typedef struct GPBMethod_Storage { .number = GPBMethod_FieldNumber_ResponseTypeURL, .hasIndex = 3, .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom, - .type = GPBTypeString, - .offset = offsetof(GPBMethod_Storage, responseTypeURL), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBMethod__storage_, responseTypeURL), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -215,10 +219,10 @@ typedef struct GPBMethod_Storage { .number = GPBMethod_FieldNumber_ResponseStreaming, .hasIndex = 4, .flags = GPBFieldOptional, - .type = GPBTypeBool, - .offset = offsetof(GPBMethod_Storage, responseStreaming), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBMethod__storage_, responseStreaming), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -226,10 +230,10 @@ typedef struct GPBMethod_Storage { .number = GPBMethod_FieldNumber_OptionsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBMethod_Storage, optionsArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBMethod__storage_, optionsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), .fieldOptions = NULL, }, }; @@ -238,20 +242,23 @@ typedef struct GPBMethod_Storage { #else static const char *extraTextFormatInfo = "\002\002\007\244\241!!\000\004\010\244\241!!\000"; #endif // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMethod class] - rootClass:[GPBApiRoot class] - file:GPBApiRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBMethod_Storage) - wireFormat:NO - extraTextFormatInfo:extraTextFormatInfo]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBMethod class] + rootClass:[GPBApiRoot class] + file:GPBApiRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBMethod__storage_) + wireFormat:NO + extraTextFormatInfo:extraTextFormatInfo]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/Descriptor.pbobjc.h b/objectivec/google/protobuf/Descriptor.pbobjc.h index 5a53abbc..bf0f51a6 100644 --- a/objectivec/google/protobuf/Descriptor.pbobjc.h +++ b/objectivec/google/protobuf/Descriptor.pbobjc.h @@ -20,6 +20,8 @@ CF_EXTERN_C_BEGIN @class GPBServiceOptions; @class GPBSourceCodeInfo; +NS_ASSUME_NONNULL_BEGIN + #pragma mark - Enum GPBFieldDescriptorProto_Type typedef GPB_ENUM(GPBFieldDescriptorProto_Type) { @@ -128,7 +130,6 @@ GPBEnumDescriptor *GPBFieldOptions_JSType_EnumDescriptor(void); BOOL GPBFieldOptions_JSType_IsValidValue(int32_t value); - #pragma mark - GPBDescriptorRoot @interface GPBDescriptorRoot : GPBRootObject @@ -151,7 +152,8 @@ typedef GPB_ENUM(GPBFileDescriptorSet_FieldNumber) { @interface GPBFileDescriptorSet : GPBMessage // |fileArray| contains |GPBFileDescriptorProto| -@property(nonatomic, readwrite, strong) NSMutableArray *fileArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *fileArray; +@property(nonatomic, readonly) NSUInteger fileArray_Count; @end @@ -177,50 +179,57 @@ typedef GPB_ENUM(GPBFileDescriptorProto_FieldNumber) { // file name, relative to root of source tree @property(nonatomic, readwrite) BOOL hasName; -@property(nonatomic, readwrite, copy) NSString *name; +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; // e.g. "foo", "foo.bar", etc. @property(nonatomic, readwrite) BOOL hasPackage; -@property(nonatomic, readwrite, copy) NSString *package; +@property(nonatomic, readwrite, copy, null_resettable) NSString *package; // Names of files imported by this file. // |dependencyArray| contains |NSString| -@property(nonatomic, readwrite, strong) NSMutableArray *dependencyArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *dependencyArray; +@property(nonatomic, readonly) NSUInteger dependencyArray_Count; // Indexes of the public imported files in the dependency list above. -@property(nonatomic, readwrite, strong) GPBInt32Array *publicDependencyArray; +@property(nonatomic, readwrite, strong, null_resettable) GPBInt32Array *publicDependencyArray; +@property(nonatomic, readonly) NSUInteger publicDependencyArray_Count; // Indexes of the weak imported files in the dependency list. // For Google-internal migration only. Do not use. -@property(nonatomic, readwrite, strong) GPBInt32Array *weakDependencyArray; +@property(nonatomic, readwrite, strong, null_resettable) GPBInt32Array *weakDependencyArray; +@property(nonatomic, readonly) NSUInteger weakDependencyArray_Count; // All top-level definitions in this file. // |messageTypeArray| contains |GPBDescriptorProto| -@property(nonatomic, readwrite, strong) NSMutableArray *messageTypeArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *messageTypeArray; +@property(nonatomic, readonly) NSUInteger messageTypeArray_Count; // |enumTypeArray| contains |GPBEnumDescriptorProto| -@property(nonatomic, readwrite, strong) NSMutableArray *enumTypeArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *enumTypeArray; +@property(nonatomic, readonly) NSUInteger enumTypeArray_Count; // |serviceArray| contains |GPBServiceDescriptorProto| -@property(nonatomic, readwrite, strong) NSMutableArray *serviceArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *serviceArray; +@property(nonatomic, readonly) NSUInteger serviceArray_Count; // |extensionArray| contains |GPBFieldDescriptorProto| -@property(nonatomic, readwrite, strong) NSMutableArray *extensionArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *extensionArray; +@property(nonatomic, readonly) NSUInteger extensionArray_Count; @property(nonatomic, readwrite) BOOL hasOptions; -@property(nonatomic, readwrite, strong) GPBFileOptions *options; +@property(nonatomic, readwrite, strong, null_resettable) 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; +@property(nonatomic, readwrite, strong, null_resettable) 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; +@property(nonatomic, readwrite, copy, null_resettable) NSString *syntax; @end @@ -243,36 +252,44 @@ typedef GPB_ENUM(GPBDescriptorProto_FieldNumber) { @interface GPBDescriptorProto : GPBMessage @property(nonatomic, readwrite) BOOL hasName; -@property(nonatomic, readwrite, copy) NSString *name; +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; // |fieldArray| contains |GPBFieldDescriptorProto| -@property(nonatomic, readwrite, strong) NSMutableArray *fieldArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *fieldArray; +@property(nonatomic, readonly) NSUInteger fieldArray_Count; // |extensionArray| contains |GPBFieldDescriptorProto| -@property(nonatomic, readwrite, strong) NSMutableArray *extensionArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *extensionArray; +@property(nonatomic, readonly) NSUInteger extensionArray_Count; // |nestedTypeArray| contains |GPBDescriptorProto| -@property(nonatomic, readwrite, strong) NSMutableArray *nestedTypeArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *nestedTypeArray; +@property(nonatomic, readonly) NSUInteger nestedTypeArray_Count; // |enumTypeArray| contains |GPBEnumDescriptorProto| -@property(nonatomic, readwrite, strong) NSMutableArray *enumTypeArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *enumTypeArray; +@property(nonatomic, readonly) NSUInteger enumTypeArray_Count; // |extensionRangeArray| contains |GPBDescriptorProto_ExtensionRange| -@property(nonatomic, readwrite, strong) NSMutableArray *extensionRangeArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *extensionRangeArray; +@property(nonatomic, readonly) NSUInteger extensionRangeArray_Count; // |oneofDeclArray| contains |GPBOneofDescriptorProto| -@property(nonatomic, readwrite, strong) NSMutableArray *oneofDeclArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *oneofDeclArray; +@property(nonatomic, readonly) NSUInteger oneofDeclArray_Count; @property(nonatomic, readwrite) BOOL hasOptions; -@property(nonatomic, readwrite, strong) GPBMessageOptions *options; +@property(nonatomic, readwrite, strong, null_resettable) GPBMessageOptions *options; // |reservedRangeArray| contains |GPBDescriptorProto_ReservedRange| -@property(nonatomic, readwrite, strong) NSMutableArray *reservedRangeArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *reservedRangeArray; +@property(nonatomic, readonly) NSUInteger reservedRangeArray_Count; // Reserved field names, which may not be used by fields in the same message. // A given name may only be reserved once. // |reservedNameArray| contains |NSString| -@property(nonatomic, readwrite, strong) NSMutableArray *reservedNameArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *reservedNameArray; +@property(nonatomic, readonly) NSUInteger reservedNameArray_Count; @end @@ -333,7 +350,7 @@ typedef GPB_ENUM(GPBFieldDescriptorProto_FieldNumber) { @interface GPBFieldDescriptorProto : GPBMessage @property(nonatomic, readwrite) BOOL hasName; -@property(nonatomic, readwrite, copy) NSString *name; +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; @property(nonatomic, readwrite) BOOL hasNumber; @property(nonatomic, readwrite) int32_t number; @@ -352,12 +369,12 @@ typedef GPB_ENUM(GPBFieldDescriptorProto_FieldNumber) { // message are searched, then within the parent, on up to the root // namespace). @property(nonatomic, readwrite) BOOL hasTypeName; -@property(nonatomic, readwrite, copy) NSString *typeName; +@property(nonatomic, readwrite, copy, null_resettable) 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; +@property(nonatomic, readwrite, copy, null_resettable) NSString *extendee; // For numeric types, contains the original text representation of the value. // For booleans, "true" or "false". @@ -365,7 +382,7 @@ typedef GPB_ENUM(GPBFieldDescriptorProto_FieldNumber) { // 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; +@property(nonatomic, readwrite, copy, null_resettable) 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. @@ -373,7 +390,7 @@ typedef GPB_ENUM(GPBFieldDescriptorProto_FieldNumber) { @property(nonatomic, readwrite) int32_t oneofIndex; @property(nonatomic, readwrite) BOOL hasOptions; -@property(nonatomic, readwrite, strong) GPBFieldOptions *options; +@property(nonatomic, readwrite, strong, null_resettable) GPBFieldOptions *options; @end @@ -387,7 +404,7 @@ typedef GPB_ENUM(GPBOneofDescriptorProto_FieldNumber) { @interface GPBOneofDescriptorProto : GPBMessage @property(nonatomic, readwrite) BOOL hasName; -@property(nonatomic, readwrite, copy) NSString *name; +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; @end @@ -403,13 +420,14 @@ typedef GPB_ENUM(GPBEnumDescriptorProto_FieldNumber) { @interface GPBEnumDescriptorProto : GPBMessage @property(nonatomic, readwrite) BOOL hasName; -@property(nonatomic, readwrite, copy) NSString *name; +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; // |valueArray| contains |GPBEnumValueDescriptorProto| -@property(nonatomic, readwrite, strong) NSMutableArray *valueArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *valueArray; +@property(nonatomic, readonly) NSUInteger valueArray_Count; @property(nonatomic, readwrite) BOOL hasOptions; -@property(nonatomic, readwrite, strong) GPBEnumOptions *options; +@property(nonatomic, readwrite, strong, null_resettable) GPBEnumOptions *options; @end @@ -425,13 +443,13 @@ typedef GPB_ENUM(GPBEnumValueDescriptorProto_FieldNumber) { @interface GPBEnumValueDescriptorProto : GPBMessage @property(nonatomic, readwrite) BOOL hasName; -@property(nonatomic, readwrite, copy) NSString *name; +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; @property(nonatomic, readwrite) BOOL hasNumber; @property(nonatomic, readwrite) int32_t number; @property(nonatomic, readwrite) BOOL hasOptions; -@property(nonatomic, readwrite, strong) GPBEnumValueOptions *options; +@property(nonatomic, readwrite, strong, null_resettable) GPBEnumValueOptions *options; @end @@ -447,13 +465,14 @@ typedef GPB_ENUM(GPBServiceDescriptorProto_FieldNumber) { @interface GPBServiceDescriptorProto : GPBMessage @property(nonatomic, readwrite) BOOL hasName; -@property(nonatomic, readwrite, copy) NSString *name; +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; // |methodArray| contains |GPBMethodDescriptorProto| -@property(nonatomic, readwrite, strong) NSMutableArray *methodArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *methodArray; +@property(nonatomic, readonly) NSUInteger methodArray_Count; @property(nonatomic, readwrite) BOOL hasOptions; -@property(nonatomic, readwrite, strong) GPBServiceOptions *options; +@property(nonatomic, readwrite, strong, null_resettable) GPBServiceOptions *options; @end @@ -472,18 +491,18 @@ typedef GPB_ENUM(GPBMethodDescriptorProto_FieldNumber) { @interface GPBMethodDescriptorProto : GPBMessage @property(nonatomic, readwrite) BOOL hasName; -@property(nonatomic, readwrite, copy) NSString *name; +@property(nonatomic, readwrite, copy, null_resettable) 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, copy, null_resettable) NSString *inputType; @property(nonatomic, readwrite) BOOL hasOutputType; -@property(nonatomic, readwrite, copy) NSString *outputType; +@property(nonatomic, readwrite, copy, null_resettable) NSString *outputType; @property(nonatomic, readwrite) BOOL hasOptions; -@property(nonatomic, readwrite, strong) GPBMethodOptions *options; +@property(nonatomic, readwrite, strong, null_resettable) GPBMethodOptions *options; // Identifies if client streams multiple client messages @property(nonatomic, readwrite) BOOL hasClientStreaming; @@ -522,7 +541,7 @@ typedef GPB_ENUM(GPBFileOptions_FieldNumber) { // inappropriate because proto packages do not normally start with backwards // domain names. @property(nonatomic, readwrite) BOOL hasJavaPackage; -@property(nonatomic, readwrite, copy) NSString *javaPackage; +@property(nonatomic, readwrite, copy, null_resettable) 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 @@ -530,7 +549,7 @@ typedef GPB_ENUM(GPBFileOptions_FieldNumber) { // 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; +@property(nonatomic, readwrite, copy, null_resettable) 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 @@ -572,7 +591,7 @@ typedef GPB_ENUM(GPBFileOptions_FieldNumber) { // - 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; +@property(nonatomic, readwrite, copy, null_resettable) 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 @@ -608,15 +627,16 @@ typedef GPB_ENUM(GPBFileOptions_FieldNumber) { // 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; +@property(nonatomic, readwrite, copy, null_resettable) NSString *objcClassPrefix; // Namespace for generated classes; defaults to the package. @property(nonatomic, readwrite) BOOL hasCsharpNamespace; -@property(nonatomic, readwrite, copy) NSString *csharpNamespace; +@property(nonatomic, readwrite, copy, null_resettable) NSString *csharpNamespace; // The parser stores options it doesn't recognize here. See above. // |uninterpretedOptionArray| contains |GPBUninterpretedOption| -@property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count; @end @@ -692,7 +712,8 @@ typedef GPB_ENUM(GPBMessageOptions_FieldNumber) { // The parser stores options it doesn't recognize here. See above. // |uninterpretedOptionArray| contains |GPBUninterpretedOption| -@property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count; @end @@ -781,7 +802,8 @@ typedef GPB_ENUM(GPBFieldOptions_FieldNumber) { // The parser stores options it doesn't recognize here. See above. // |uninterpretedOptionArray| contains |GPBUninterpretedOption| -@property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count; @end @@ -809,7 +831,8 @@ typedef GPB_ENUM(GPBEnumOptions_FieldNumber) { // The parser stores options it doesn't recognize here. See above. // |uninterpretedOptionArray| contains |GPBUninterpretedOption| -@property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count; @end @@ -831,7 +854,8 @@ typedef GPB_ENUM(GPBEnumValueOptions_FieldNumber) { // The parser stores options it doesn't recognize here. See above. // |uninterpretedOptionArray| contains |GPBUninterpretedOption| -@property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count; @end @@ -853,7 +877,8 @@ typedef GPB_ENUM(GPBServiceOptions_FieldNumber) { // The parser stores options it doesn't recognize here. See above. // |uninterpretedOptionArray| contains |GPBUninterpretedOption| -@property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count; @end @@ -875,7 +900,8 @@ typedef GPB_ENUM(GPBMethodOptions_FieldNumber) { // The parser stores options it doesn't recognize here. See above. // |uninterpretedOptionArray| contains |GPBUninterpretedOption| -@property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count; @end @@ -900,12 +926,13 @@ typedef GPB_ENUM(GPBUninterpretedOption_FieldNumber) { @interface GPBUninterpretedOption : GPBMessage // |nameArray| contains |GPBUninterpretedOption_NamePart| -@property(nonatomic, readwrite, strong) NSMutableArray *nameArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *nameArray; +@property(nonatomic, readonly) NSUInteger nameArray_Count; // 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, copy, null_resettable) NSString *identifierValue; @property(nonatomic, readwrite) BOOL hasPositiveIntValue; @property(nonatomic, readwrite) uint64_t positiveIntValue; @@ -917,10 +944,10 @@ typedef GPB_ENUM(GPBUninterpretedOption_FieldNumber) { @property(nonatomic, readwrite) double doubleValue; @property(nonatomic, readwrite) BOOL hasStringValue; -@property(nonatomic, readwrite, copy) NSData *stringValue; +@property(nonatomic, readwrite, copy, null_resettable) NSData *stringValue; @property(nonatomic, readwrite) BOOL hasAggregateValue; -@property(nonatomic, readwrite, copy) NSString *aggregateValue; +@property(nonatomic, readwrite, copy, null_resettable) NSString *aggregateValue; @end @@ -939,7 +966,7 @@ typedef GPB_ENUM(GPBUninterpretedOption_NamePart_FieldNumber) { @interface GPBUninterpretedOption_NamePart : GPBMessage @property(nonatomic, readwrite) BOOL hasNamePart; -@property(nonatomic, readwrite, copy) NSString *namePart; +@property(nonatomic, readwrite, copy, null_resettable) NSString *namePart; @property(nonatomic, readwrite) BOOL hasIsExtension; @property(nonatomic, readwrite) BOOL isExtension; @@ -1000,7 +1027,8 @@ typedef GPB_ENUM(GPBSourceCodeInfo_FieldNumber) { // 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; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *locationArray; +@property(nonatomic, readonly) NSUInteger locationArray_Count; @end @@ -1039,14 +1067,16 @@ typedef GPB_ENUM(GPBSourceCodeInfo_Location_FieldNumber) { // [ 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; +@property(nonatomic, readwrite, strong, null_resettable) GPBInt32Array *pathArray; +@property(nonatomic, readonly) NSUInteger pathArray_Count; // 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; +@property(nonatomic, readwrite, strong, null_resettable) GPBInt32Array *spanArray; +@property(nonatomic, readonly) NSUInteger spanArray_Count; // If this SourceCodeInfo represents a complete declaration, these are any // comments appearing before and after the declaration which appear to be @@ -1096,16 +1126,19 @@ typedef GPB_ENUM(GPBSourceCodeInfo_Location_FieldNumber) { // // // ignored detached comments. @property(nonatomic, readwrite) BOOL hasLeadingComments; -@property(nonatomic, readwrite, copy) NSString *leadingComments; +@property(nonatomic, readwrite, copy, null_resettable) NSString *leadingComments; @property(nonatomic, readwrite) BOOL hasTrailingComments; -@property(nonatomic, readwrite, copy) NSString *trailingComments; +@property(nonatomic, readwrite, copy, null_resettable) NSString *trailingComments; // |leadingDetachedCommentsArray| contains |NSString| -@property(nonatomic, readwrite, strong) NSMutableArray *leadingDetachedCommentsArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *leadingDetachedCommentsArray; +@property(nonatomic, readonly) NSUInteger leadingDetachedCommentsArray_Count; @end +NS_ASSUME_NONNULL_END + CF_EXTERN_C_END // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Descriptor.pbobjc.m b/objectivec/google/protobuf/Descriptor.pbobjc.m index 7f1bdd49..8c535b9a 100644 --- a/objectivec/google/protobuf/Descriptor.pbobjc.m +++ b/objectivec/google/protobuf/Descriptor.pbobjc.m @@ -11,11 +11,14 @@ @end +#pragma mark - GPBDescriptorRoot_FileDescriptor + 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) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto2]; } @@ -26,17 +29,17 @@ static GPBFileDescriptor *GPBDescriptorRoot_FileDescriptor(void) { @implementation GPBFileDescriptorSet -@dynamic fileArray; +@dynamic fileArray, fileArray_Count; -typedef struct GPBFileDescriptorSet_Storage { +typedef struct GPBFileDescriptorSet__storage_ { uint32_t _has_storage_[1]; NSMutableArray *fileArray; -} GPBFileDescriptorSet_Storage; +} GPBFileDescriptorSet__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -44,26 +47,29 @@ typedef struct GPBFileDescriptorSet_Storage { .number = GPBFileDescriptorSet_FieldNumber_FileArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBFileDescriptorSet_Storage, fileArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFileDescriptorSet__storage_, fileArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBFileDescriptorProto), + .dataTypeSpecific.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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -76,18 +82,18 @@ typedef struct GPBFileDescriptorSet_Storage { @dynamic hasName, name; @dynamic hasPackage, package; -@dynamic dependencyArray; -@dynamic publicDependencyArray; -@dynamic weakDependencyArray; -@dynamic messageTypeArray; -@dynamic enumTypeArray; -@dynamic serviceArray; -@dynamic extensionArray; +@dynamic dependencyArray, dependencyArray_Count; +@dynamic publicDependencyArray, publicDependencyArray_Count; +@dynamic weakDependencyArray, weakDependencyArray_Count; +@dynamic messageTypeArray, messageTypeArray_Count; +@dynamic enumTypeArray, enumTypeArray_Count; +@dynamic serviceArray, serviceArray_Count; +@dynamic extensionArray, extensionArray_Count; @dynamic hasOptions, options; @dynamic hasSourceCodeInfo, sourceCodeInfo; @dynamic hasSyntax, syntax; -typedef struct GPBFileDescriptorProto_Storage { +typedef struct GPBFileDescriptorProto__storage_ { uint32_t _has_storage_[1]; NSString *name; NSString *package; @@ -101,12 +107,12 @@ typedef struct GPBFileDescriptorProto_Storage { GPBInt32Array *publicDependencyArray; GPBInt32Array *weakDependencyArray; NSString *syntax; -} GPBFileDescriptorProto_Storage; +} GPBFileDescriptorProto__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -114,10 +120,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFileDescriptorProto_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFileDescriptorProto__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -125,10 +131,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_Package, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFileDescriptorProto_Storage, package), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFileDescriptorProto__storage_, package), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -136,10 +142,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_DependencyArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeString, - .offset = offsetof(GPBFileDescriptorProto_Storage, dependencyArray), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFileDescriptorProto__storage_, dependencyArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -147,10 +153,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_MessageTypeArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBFileDescriptorProto_Storage, messageTypeArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFileDescriptorProto__storage_, messageTypeArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBDescriptorProto), .fieldOptions = NULL, }, { @@ -158,10 +164,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_EnumTypeArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBFileDescriptorProto_Storage, enumTypeArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFileDescriptorProto__storage_, enumTypeArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBEnumDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumDescriptorProto), .fieldOptions = NULL, }, { @@ -169,10 +175,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_ServiceArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBFileDescriptorProto_Storage, serviceArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFileDescriptorProto__storage_, serviceArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBServiceDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBServiceDescriptorProto), .fieldOptions = NULL, }, { @@ -180,10 +186,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_ExtensionArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBFileDescriptorProto_Storage, extensionArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFileDescriptorProto__storage_, extensionArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto), .fieldOptions = NULL, }, { @@ -191,10 +197,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_Options, .hasIndex = 9, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBFileDescriptorProto_Storage, options), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFileDescriptorProto__storage_, options), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBFileOptions), + .dataTypeSpecific.className = GPBStringifySymbol(GPBFileOptions), .fieldOptions = NULL, }, { @@ -202,10 +208,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_SourceCodeInfo, .hasIndex = 10, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBFileDescriptorProto_Storage, sourceCodeInfo), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFileDescriptorProto__storage_, sourceCodeInfo), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBSourceCodeInfo), + .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceCodeInfo), .fieldOptions = NULL, }, { @@ -213,10 +219,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_PublicDependencyArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeInt32, - .offset = offsetof(GPBFileDescriptorProto_Storage, publicDependencyArray), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBFileDescriptorProto__storage_, publicDependencyArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -224,10 +230,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_WeakDependencyArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeInt32, - .offset = offsetof(GPBFileDescriptorProto_Storage, weakDependencyArray), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBFileDescriptorProto__storage_, weakDependencyArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -235,26 +241,29 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_Syntax, .hasIndex = 11, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFileDescriptorProto_Storage, syntax), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFileDescriptorProto__storage_, syntax), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -266,17 +275,17 @@ typedef struct GPBFileDescriptorProto_Storage { @implementation GPBDescriptorProto @dynamic hasName, name; -@dynamic fieldArray; -@dynamic extensionArray; -@dynamic nestedTypeArray; -@dynamic enumTypeArray; -@dynamic extensionRangeArray; -@dynamic oneofDeclArray; +@dynamic fieldArray, fieldArray_Count; +@dynamic extensionArray, extensionArray_Count; +@dynamic nestedTypeArray, nestedTypeArray_Count; +@dynamic enumTypeArray, enumTypeArray_Count; +@dynamic extensionRangeArray, extensionRangeArray_Count; +@dynamic oneofDeclArray, oneofDeclArray_Count; @dynamic hasOptions, options; -@dynamic reservedRangeArray; -@dynamic reservedNameArray; +@dynamic reservedRangeArray, reservedRangeArray_Count; +@dynamic reservedNameArray, reservedNameArray_Count; -typedef struct GPBDescriptorProto_Storage { +typedef struct GPBDescriptorProto__storage_ { uint32_t _has_storage_[1]; NSString *name; NSMutableArray *fieldArray; @@ -288,12 +297,12 @@ typedef struct GPBDescriptorProto_Storage { NSMutableArray *oneofDeclArray; NSMutableArray *reservedRangeArray; NSMutableArray *reservedNameArray; -} GPBDescriptorProto_Storage; +} GPBDescriptorProto__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -301,10 +310,10 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBDescriptorProto_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBDescriptorProto__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -312,10 +321,10 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_FieldArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBDescriptorProto_Storage, fieldArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBDescriptorProto__storage_, fieldArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto), .fieldOptions = NULL, }, { @@ -323,10 +332,10 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_NestedTypeArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBDescriptorProto_Storage, nestedTypeArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBDescriptorProto__storage_, nestedTypeArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBDescriptorProto), .fieldOptions = NULL, }, { @@ -334,10 +343,10 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_EnumTypeArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBDescriptorProto_Storage, enumTypeArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBDescriptorProto__storage_, enumTypeArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBEnumDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumDescriptorProto), .fieldOptions = NULL, }, { @@ -345,10 +354,10 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_ExtensionRangeArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBDescriptorProto_Storage, extensionRangeArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBDescriptorProto__storage_, extensionRangeArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBDescriptorProto_ExtensionRange), + .dataTypeSpecific.className = GPBStringifySymbol(GPBDescriptorProto_ExtensionRange), .fieldOptions = NULL, }, { @@ -356,10 +365,10 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_ExtensionArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBDescriptorProto_Storage, extensionArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBDescriptorProto__storage_, extensionArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto), .fieldOptions = NULL, }, { @@ -367,10 +376,10 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_Options, .hasIndex = 7, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBDescriptorProto_Storage, options), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBDescriptorProto__storage_, options), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBMessageOptions), + .dataTypeSpecific.className = GPBStringifySymbol(GPBMessageOptions), .fieldOptions = NULL, }, { @@ -378,10 +387,10 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_OneofDeclArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBDescriptorProto_Storage, oneofDeclArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBDescriptorProto__storage_, oneofDeclArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBOneofDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBOneofDescriptorProto), .fieldOptions = NULL, }, { @@ -389,10 +398,10 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_ReservedRangeArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBDescriptorProto_Storage, reservedRangeArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBDescriptorProto__storage_, reservedRangeArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBDescriptorProto_ReservedRange), + .dataTypeSpecific.className = GPBStringifySymbol(GPBDescriptorProto_ReservedRange), .fieldOptions = NULL, }, { @@ -400,26 +409,29 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_ReservedNameArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeString, - .offset = offsetof(GPBDescriptorProto_Storage, reservedNameArray), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBDescriptorProto__storage_, reservedNameArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -433,16 +445,16 @@ typedef struct GPBDescriptorProto_Storage { @dynamic hasStart, start; @dynamic hasEnd, end; -typedef struct GPBDescriptorProto_ExtensionRange_Storage { +typedef struct GPBDescriptorProto_ExtensionRange__storage_ { uint32_t _has_storage_[1]; int32_t start; int32_t end; -} GPBDescriptorProto_ExtensionRange_Storage; +} GPBDescriptorProto_ExtensionRange__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -450,10 +462,10 @@ typedef struct GPBDescriptorProto_ExtensionRange_Storage { .number = GPBDescriptorProto_ExtensionRange_FieldNumber_Start, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBDescriptorProto_ExtensionRange_Storage, start), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBDescriptorProto_ExtensionRange__storage_, start), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -461,26 +473,29 @@ typedef struct GPBDescriptorProto_ExtensionRange_Storage { .number = GPBDescriptorProto_ExtensionRange_FieldNumber_End, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBDescriptorProto_ExtensionRange_Storage, end), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBDescriptorProto_ExtensionRange__storage_, end), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -494,16 +509,16 @@ typedef struct GPBDescriptorProto_ExtensionRange_Storage { @dynamic hasStart, start; @dynamic hasEnd, end; -typedef struct GPBDescriptorProto_ReservedRange_Storage { +typedef struct GPBDescriptorProto_ReservedRange__storage_ { uint32_t _has_storage_[1]; int32_t start; int32_t end; -} GPBDescriptorProto_ReservedRange_Storage; +} GPBDescriptorProto_ReservedRange__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -511,10 +526,10 @@ typedef struct GPBDescriptorProto_ReservedRange_Storage { .number = GPBDescriptorProto_ReservedRange_FieldNumber_Start, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBDescriptorProto_ReservedRange_Storage, start), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBDescriptorProto_ReservedRange__storage_, start), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -522,26 +537,29 @@ typedef struct GPBDescriptorProto_ReservedRange_Storage { .number = GPBDescriptorProto_ReservedRange_FieldNumber_End, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBDescriptorProto_ReservedRange_Storage, end), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBDescriptorProto_ReservedRange__storage_, end), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBDescriptorProto_ReservedRange 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_ReservedRange_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBDescriptorProto_ReservedRange 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_ReservedRange__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -562,7 +580,7 @@ typedef struct GPBDescriptorProto_ReservedRange_Storage { @dynamic hasOneofIndex, oneofIndex; @dynamic hasOptions, options; -typedef struct GPBFieldDescriptorProto_Storage { +typedef struct GPBFieldDescriptorProto__storage_ { uint32_t _has_storage_[1]; int32_t number; GPBFieldDescriptorProto_Label label; @@ -573,12 +591,12 @@ typedef struct GPBFieldDescriptorProto_Storage { NSString *typeName; NSString *defaultValue; GPBFieldOptions *options; -} GPBFieldDescriptorProto_Storage; +} GPBFieldDescriptorProto__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -586,10 +604,10 @@ typedef struct GPBFieldDescriptorProto_Storage { .number = GPBFieldDescriptorProto_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFieldDescriptorProto_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFieldDescriptorProto__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -597,10 +615,10 @@ typedef struct GPBFieldDescriptorProto_Storage { .number = GPBFieldDescriptorProto_FieldNumber_Extendee, .hasIndex = 5, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFieldDescriptorProto_Storage, extendee), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFieldDescriptorProto__storage_, extendee), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -608,10 +626,10 @@ typedef struct GPBFieldDescriptorProto_Storage { .number = GPBFieldDescriptorProto_FieldNumber_Number, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBFieldDescriptorProto_Storage, number), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBFieldDescriptorProto__storage_, number), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -619,10 +637,10 @@ typedef struct GPBFieldDescriptorProto_Storage { .number = GPBFieldDescriptorProto_FieldNumber_Label, .hasIndex = 2, .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, - .type = GPBTypeEnum, - .offset = offsetof(GPBFieldDescriptorProto_Storage, label), + .dataType = GPBDataTypeEnum, + .offset = offsetof(GPBFieldDescriptorProto__storage_, label), .defaultValue.valueEnum = GPBFieldDescriptorProto_Label_LabelOptional, - .typeSpecific.enumDescFunc = GPBFieldDescriptorProto_Label_EnumDescriptor, + .dataTypeSpecific.enumDescFunc = GPBFieldDescriptorProto_Label_EnumDescriptor, .fieldOptions = NULL, }, { @@ -630,10 +648,10 @@ typedef struct GPBFieldDescriptorProto_Storage { .number = GPBFieldDescriptorProto_FieldNumber_Type, .hasIndex = 3, .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, - .type = GPBTypeEnum, - .offset = offsetof(GPBFieldDescriptorProto_Storage, type), + .dataType = GPBDataTypeEnum, + .offset = offsetof(GPBFieldDescriptorProto__storage_, type), .defaultValue.valueEnum = GPBFieldDescriptorProto_Type_TypeDouble, - .typeSpecific.enumDescFunc = GPBFieldDescriptorProto_Type_EnumDescriptor, + .dataTypeSpecific.enumDescFunc = GPBFieldDescriptorProto_Type_EnumDescriptor, .fieldOptions = NULL, }, { @@ -641,10 +659,10 @@ typedef struct GPBFieldDescriptorProto_Storage { .number = GPBFieldDescriptorProto_FieldNumber_TypeName, .hasIndex = 4, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFieldDescriptorProto_Storage, typeName), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFieldDescriptorProto__storage_, typeName), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -652,10 +670,10 @@ typedef struct GPBFieldDescriptorProto_Storage { .number = GPBFieldDescriptorProto_FieldNumber_DefaultValue, .hasIndex = 6, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFieldDescriptorProto_Storage, defaultValue), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFieldDescriptorProto__storage_, defaultValue), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -663,10 +681,10 @@ typedef struct GPBFieldDescriptorProto_Storage { .number = GPBFieldDescriptorProto_FieldNumber_Options, .hasIndex = 8, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBFieldDescriptorProto_Storage, options), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFieldDescriptorProto__storage_, options), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBFieldOptions), + .dataTypeSpecific.className = GPBStringifySymbol(GPBFieldOptions), .fieldOptions = NULL, }, { @@ -674,10 +692,10 @@ typedef struct GPBFieldDescriptorProto_Storage { .number = GPBFieldDescriptorProto_FieldNumber_OneofIndex, .hasIndex = 7, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBFieldDescriptorProto_Storage, oneofIndex), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBFieldDescriptorProto__storage_, oneofIndex), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; @@ -685,19 +703,22 @@ typedef struct GPBFieldDescriptorProto_Storage { { .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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -798,15 +819,15 @@ BOOL GPBFieldDescriptorProto_Label_IsValidValue(int32_t value__) { @dynamic hasName, name; -typedef struct GPBOneofDescriptorProto_Storage { +typedef struct GPBOneofDescriptorProto__storage_ { uint32_t _has_storage_[1]; NSString *name; -} GPBOneofDescriptorProto_Storage; +} GPBOneofDescriptorProto__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -814,26 +835,29 @@ typedef struct GPBOneofDescriptorProto_Storage { .number = GPBOneofDescriptorProto_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBOneofDescriptorProto_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBOneofDescriptorProto__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -845,20 +869,20 @@ typedef struct GPBOneofDescriptorProto_Storage { @implementation GPBEnumDescriptorProto @dynamic hasName, name; -@dynamic valueArray; +@dynamic valueArray, valueArray_Count; @dynamic hasOptions, options; -typedef struct GPBEnumDescriptorProto_Storage { +typedef struct GPBEnumDescriptorProto__storage_ { uint32_t _has_storage_[1]; NSString *name; NSMutableArray *valueArray; GPBEnumOptions *options; -} GPBEnumDescriptorProto_Storage; +} GPBEnumDescriptorProto__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -866,10 +890,10 @@ typedef struct GPBEnumDescriptorProto_Storage { .number = GPBEnumDescriptorProto_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBEnumDescriptorProto_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBEnumDescriptorProto__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -877,10 +901,10 @@ typedef struct GPBEnumDescriptorProto_Storage { .number = GPBEnumDescriptorProto_FieldNumber_ValueArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBEnumDescriptorProto_Storage, valueArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBEnumDescriptorProto__storage_, valueArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBEnumValueDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumValueDescriptorProto), .fieldOptions = NULL, }, { @@ -888,26 +912,29 @@ typedef struct GPBEnumDescriptorProto_Storage { .number = GPBEnumDescriptorProto_FieldNumber_Options, .hasIndex = 2, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBEnumDescriptorProto_Storage, options), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBEnumDescriptorProto__storage_, options), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBEnumOptions), + .dataTypeSpecific.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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -922,17 +949,17 @@ typedef struct GPBEnumDescriptorProto_Storage { @dynamic hasNumber, number; @dynamic hasOptions, options; -typedef struct GPBEnumValueDescriptorProto_Storage { +typedef struct GPBEnumValueDescriptorProto__storage_ { uint32_t _has_storage_[1]; int32_t number; NSString *name; GPBEnumValueOptions *options; -} GPBEnumValueDescriptorProto_Storage; +} GPBEnumValueDescriptorProto__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -940,10 +967,10 @@ typedef struct GPBEnumValueDescriptorProto_Storage { .number = GPBEnumValueDescriptorProto_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBEnumValueDescriptorProto_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBEnumValueDescriptorProto__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -951,10 +978,10 @@ typedef struct GPBEnumValueDescriptorProto_Storage { .number = GPBEnumValueDescriptorProto_FieldNumber_Number, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBEnumValueDescriptorProto_Storage, number), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBEnumValueDescriptorProto__storage_, number), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -962,26 +989,29 @@ typedef struct GPBEnumValueDescriptorProto_Storage { .number = GPBEnumValueDescriptorProto_FieldNumber_Options, .hasIndex = 2, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBEnumValueDescriptorProto_Storage, options), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBEnumValueDescriptorProto__storage_, options), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBEnumValueOptions), + .dataTypeSpecific.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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -993,20 +1023,20 @@ typedef struct GPBEnumValueDescriptorProto_Storage { @implementation GPBServiceDescriptorProto @dynamic hasName, name; -@dynamic methodArray; +@dynamic methodArray, methodArray_Count; @dynamic hasOptions, options; -typedef struct GPBServiceDescriptorProto_Storage { +typedef struct GPBServiceDescriptorProto__storage_ { uint32_t _has_storage_[1]; NSString *name; NSMutableArray *methodArray; GPBServiceOptions *options; -} GPBServiceDescriptorProto_Storage; +} GPBServiceDescriptorProto__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -1014,10 +1044,10 @@ typedef struct GPBServiceDescriptorProto_Storage { .number = GPBServiceDescriptorProto_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBServiceDescriptorProto_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBServiceDescriptorProto__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1025,10 +1055,10 @@ typedef struct GPBServiceDescriptorProto_Storage { .number = GPBServiceDescriptorProto_FieldNumber_MethodArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBServiceDescriptorProto_Storage, methodArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBServiceDescriptorProto__storage_, methodArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBMethodDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBMethodDescriptorProto), .fieldOptions = NULL, }, { @@ -1036,26 +1066,29 @@ typedef struct GPBServiceDescriptorProto_Storage { .number = GPBServiceDescriptorProto_FieldNumber_Options, .hasIndex = 2, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBServiceDescriptorProto_Storage, options), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBServiceDescriptorProto__storage_, options), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBServiceOptions), + .dataTypeSpecific.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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -1073,7 +1106,7 @@ typedef struct GPBServiceDescriptorProto_Storage { @dynamic hasClientStreaming, clientStreaming; @dynamic hasServerStreaming, serverStreaming; -typedef struct GPBMethodDescriptorProto_Storage { +typedef struct GPBMethodDescriptorProto__storage_ { uint32_t _has_storage_[1]; BOOL clientStreaming; BOOL serverStreaming; @@ -1081,12 +1114,12 @@ typedef struct GPBMethodDescriptorProto_Storage { NSString *inputType; NSString *outputType; GPBMethodOptions *options; -} GPBMethodDescriptorProto_Storage; +} GPBMethodDescriptorProto__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -1094,10 +1127,10 @@ typedef struct GPBMethodDescriptorProto_Storage { .number = GPBMethodDescriptorProto_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBMethodDescriptorProto_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBMethodDescriptorProto__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1105,10 +1138,10 @@ typedef struct GPBMethodDescriptorProto_Storage { .number = GPBMethodDescriptorProto_FieldNumber_InputType, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBMethodDescriptorProto_Storage, inputType), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBMethodDescriptorProto__storage_, inputType), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1116,10 +1149,10 @@ typedef struct GPBMethodDescriptorProto_Storage { .number = GPBMethodDescriptorProto_FieldNumber_OutputType, .hasIndex = 2, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBMethodDescriptorProto_Storage, outputType), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBMethodDescriptorProto__storage_, outputType), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1127,10 +1160,10 @@ typedef struct GPBMethodDescriptorProto_Storage { .number = GPBMethodDescriptorProto_FieldNumber_Options, .hasIndex = 3, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBMethodDescriptorProto_Storage, options), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBMethodDescriptorProto__storage_, options), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBMethodOptions), + .dataTypeSpecific.className = GPBStringifySymbol(GPBMethodOptions), .fieldOptions = NULL, }, { @@ -1138,10 +1171,10 @@ typedef struct GPBMethodDescriptorProto_Storage { .number = GPBMethodDescriptorProto_FieldNumber_ClientStreaming, .hasIndex = 4, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBMethodDescriptorProto_Storage, clientStreaming), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBMethodDescriptorProto__storage_, clientStreaming), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1149,26 +1182,29 @@ typedef struct GPBMethodDescriptorProto_Storage { .number = GPBMethodDescriptorProto_FieldNumber_ServerStreaming, .hasIndex = 5, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBMethodDescriptorProto_Storage, serverStreaming), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBMethodDescriptorProto__storage_, serverStreaming), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -1193,9 +1229,9 @@ typedef struct GPBMethodDescriptorProto_Storage { @dynamic hasCcEnableArenas, ccEnableArenas; @dynamic hasObjcClassPrefix, objcClassPrefix; @dynamic hasCsharpNamespace, csharpNamespace; -@dynamic uninterpretedOptionArray; +@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count; -typedef struct GPBFileOptions_Storage { +typedef struct GPBFileOptions__storage_ { uint32_t _has_storage_[1]; BOOL javaMultipleFiles; BOOL ccGenericServices; @@ -1212,12 +1248,12 @@ typedef struct GPBFileOptions_Storage { NSString *objcClassPrefix; NSString *csharpNamespace; NSMutableArray *uninterpretedOptionArray; -} GPBFileOptions_Storage; +} GPBFileOptions__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -1225,10 +1261,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_JavaPackage, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFileOptions_Storage, javaPackage), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFileOptions__storage_, javaPackage), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1236,10 +1272,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_JavaOuterClassname, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFileOptions_Storage, javaOuterClassname), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFileOptions__storage_, javaOuterClassname), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1247,10 +1283,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_OptimizeFor, .hasIndex = 5, .flags = GPBFieldOptional | GPBFieldHasDefaultValue | GPBFieldHasEnumDescriptor, - .type = GPBTypeEnum, - .offset = offsetof(GPBFileOptions_Storage, optimizeFor), + .dataType = GPBDataTypeEnum, + .offset = offsetof(GPBFileOptions__storage_, optimizeFor), .defaultValue.valueEnum = GPBFileOptions_OptimizeMode_Speed, - .typeSpecific.enumDescFunc = GPBFileOptions_OptimizeMode_EnumDescriptor, + .dataTypeSpecific.enumDescFunc = GPBFileOptions_OptimizeMode_EnumDescriptor, .fieldOptions = NULL, }, { @@ -1258,10 +1294,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_JavaMultipleFiles, .hasIndex = 2, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFileOptions_Storage, javaMultipleFiles), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFileOptions__storage_, javaMultipleFiles), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1269,10 +1305,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_GoPackage, .hasIndex = 6, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFileOptions_Storage, goPackage), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFileOptions__storage_, goPackage), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1280,10 +1316,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_CcGenericServices, .hasIndex = 7, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFileOptions_Storage, ccGenericServices), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFileOptions__storage_, ccGenericServices), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1291,10 +1327,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_JavaGenericServices, .hasIndex = 8, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFileOptions_Storage, javaGenericServices), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFileOptions__storage_, javaGenericServices), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1302,10 +1338,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_PyGenericServices, .hasIndex = 9, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFileOptions_Storage, pyGenericServices), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFileOptions__storage_, pyGenericServices), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1313,10 +1349,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_JavaGenerateEqualsAndHash, .hasIndex = 3, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFileOptions_Storage, javaGenerateEqualsAndHash), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFileOptions__storage_, javaGenerateEqualsAndHash), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1324,10 +1360,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_Deprecated, .hasIndex = 10, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFileOptions_Storage, deprecated), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFileOptions__storage_, deprecated), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1335,10 +1371,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_JavaStringCheckUtf8, .hasIndex = 4, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFileOptions_Storage, javaStringCheckUtf8), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFileOptions__storage_, javaStringCheckUtf8), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1346,10 +1382,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_CcEnableArenas, .hasIndex = 11, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFileOptions_Storage, ccEnableArenas), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFileOptions__storage_, ccEnableArenas), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1357,10 +1393,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_ObjcClassPrefix, .hasIndex = 12, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFileOptions_Storage, objcClassPrefix), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFileOptions__storage_, objcClassPrefix), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1368,10 +1404,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_CsharpNamespace, .hasIndex = 13, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFileOptions_Storage, csharpNamespace), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFileOptions__storage_, csharpNamespace), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1379,10 +1415,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_UninterpretedOptionArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBFileOptions_Storage, uninterpretedOptionArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFileOptions__storage_, uninterpretedOptionArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), .fieldOptions = NULL, }, }; @@ -1392,19 +1428,22 @@ typedef struct GPBFileOptions_Storage { 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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -1448,21 +1487,21 @@ BOOL GPBFileOptions_OptimizeMode_IsValidValue(int32_t value__) { @dynamic hasNoStandardDescriptorAccessor, noStandardDescriptorAccessor; @dynamic hasDeprecated, deprecated; @dynamic hasMapEntry, mapEntry; -@dynamic uninterpretedOptionArray; +@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count; -typedef struct GPBMessageOptions_Storage { +typedef struct GPBMessageOptions__storage_ { uint32_t _has_storage_[1]; BOOL messageSetWireFormat; BOOL noStandardDescriptorAccessor; BOOL deprecated; BOOL mapEntry; NSMutableArray *uninterpretedOptionArray; -} GPBMessageOptions_Storage; +} GPBMessageOptions__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -1470,10 +1509,10 @@ typedef struct GPBMessageOptions_Storage { .number = GPBMessageOptions_FieldNumber_MessageSetWireFormat, .hasIndex = 0, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBMessageOptions_Storage, messageSetWireFormat), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBMessageOptions__storage_, messageSetWireFormat), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1481,10 +1520,10 @@ typedef struct GPBMessageOptions_Storage { .number = GPBMessageOptions_FieldNumber_NoStandardDescriptorAccessor, .hasIndex = 1, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBMessageOptions_Storage, noStandardDescriptorAccessor), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBMessageOptions__storage_, noStandardDescriptorAccessor), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1492,10 +1531,10 @@ typedef struct GPBMessageOptions_Storage { .number = GPBMessageOptions_FieldNumber_Deprecated, .hasIndex = 2, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBMessageOptions_Storage, deprecated), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBMessageOptions__storage_, deprecated), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1503,10 +1542,10 @@ typedef struct GPBMessageOptions_Storage { .number = GPBMessageOptions_FieldNumber_MapEntry, .hasIndex = 3, .flags = GPBFieldOptional, - .type = GPBTypeBool, - .offset = offsetof(GPBMessageOptions_Storage, mapEntry), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBMessageOptions__storage_, mapEntry), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1514,29 +1553,32 @@ typedef struct GPBMessageOptions_Storage { .number = GPBMessageOptions_FieldNumber_UninterpretedOptionArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBMessageOptions_Storage, uninterpretedOptionArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBMessageOptions__storage_, uninterpretedOptionArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), + .dataTypeSpecific.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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -1553,9 +1595,9 @@ typedef struct GPBMessageOptions_Storage { @dynamic hasLazy, lazy; @dynamic hasDeprecated, deprecated; @dynamic hasWeak, weak; -@dynamic uninterpretedOptionArray; +@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count; -typedef struct GPBFieldOptions_Storage { +typedef struct GPBFieldOptions__storage_ { uint32_t _has_storage_[1]; BOOL packed; BOOL deprecated; @@ -1564,12 +1606,12 @@ typedef struct GPBFieldOptions_Storage { GPBFieldOptions_CType ctype; GPBFieldOptions_JSType jstype; NSMutableArray *uninterpretedOptionArray; -} GPBFieldOptions_Storage; +} GPBFieldOptions__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -1577,10 +1619,10 @@ typedef struct GPBFieldOptions_Storage { .number = GPBFieldOptions_FieldNumber_Ctype, .hasIndex = 0, .flags = GPBFieldOptional | GPBFieldHasDefaultValue | GPBFieldHasEnumDescriptor, - .type = GPBTypeEnum, - .offset = offsetof(GPBFieldOptions_Storage, ctype), + .dataType = GPBDataTypeEnum, + .offset = offsetof(GPBFieldOptions__storage_, ctype), .defaultValue.valueEnum = GPBFieldOptions_CType_String, - .typeSpecific.enumDescFunc = GPBFieldOptions_CType_EnumDescriptor, + .dataTypeSpecific.enumDescFunc = GPBFieldOptions_CType_EnumDescriptor, .fieldOptions = NULL, }, { @@ -1588,10 +1630,10 @@ typedef struct GPBFieldOptions_Storage { .number = GPBFieldOptions_FieldNumber_Packed, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeBool, - .offset = offsetof(GPBFieldOptions_Storage, packed), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFieldOptions__storage_, packed), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1599,10 +1641,10 @@ typedef struct GPBFieldOptions_Storage { .number = GPBFieldOptions_FieldNumber_Deprecated, .hasIndex = 4, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFieldOptions_Storage, deprecated), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFieldOptions__storage_, deprecated), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1610,10 +1652,10 @@ typedef struct GPBFieldOptions_Storage { .number = GPBFieldOptions_FieldNumber_Lazy, .hasIndex = 3, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFieldOptions_Storage, lazy), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFieldOptions__storage_, lazy), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1621,10 +1663,10 @@ typedef struct GPBFieldOptions_Storage { .number = GPBFieldOptions_FieldNumber_Jstype, .hasIndex = 2, .flags = GPBFieldOptional | GPBFieldHasDefaultValue | GPBFieldHasEnumDescriptor, - .type = GPBTypeEnum, - .offset = offsetof(GPBFieldOptions_Storage, jstype), + .dataType = GPBDataTypeEnum, + .offset = offsetof(GPBFieldOptions__storage_, jstype), .defaultValue.valueEnum = GPBFieldOptions_JSType_JsNormal, - .typeSpecific.enumDescFunc = GPBFieldOptions_JSType_EnumDescriptor, + .dataTypeSpecific.enumDescFunc = GPBFieldOptions_JSType_EnumDescriptor, .fieldOptions = NULL, }, { @@ -1632,10 +1674,10 @@ typedef struct GPBFieldOptions_Storage { .number = GPBFieldOptions_FieldNumber_Weak, .hasIndex = 5, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFieldOptions_Storage, weak), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFieldOptions__storage_, weak), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1643,10 +1685,10 @@ typedef struct GPBFieldOptions_Storage { .number = GPBFieldOptions_FieldNumber_UninterpretedOptionArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBFieldOptions_Storage, uninterpretedOptionArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFieldOptions__storage_, uninterpretedOptionArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), .fieldOptions = NULL, }, }; @@ -1657,19 +1699,22 @@ typedef struct GPBFieldOptions_Storage { 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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -1740,19 +1785,19 @@ BOOL GPBFieldOptions_JSType_IsValidValue(int32_t value__) { @dynamic hasAllowAlias, allowAlias; @dynamic hasDeprecated, deprecated; -@dynamic uninterpretedOptionArray; +@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count; -typedef struct GPBEnumOptions_Storage { +typedef struct GPBEnumOptions__storage_ { uint32_t _has_storage_[1]; BOOL allowAlias; BOOL deprecated; NSMutableArray *uninterpretedOptionArray; -} GPBEnumOptions_Storage; +} GPBEnumOptions__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -1760,10 +1805,10 @@ typedef struct GPBEnumOptions_Storage { .number = GPBEnumOptions_FieldNumber_AllowAlias, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeBool, - .offset = offsetof(GPBEnumOptions_Storage, allowAlias), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBEnumOptions__storage_, allowAlias), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1771,10 +1816,10 @@ typedef struct GPBEnumOptions_Storage { .number = GPBEnumOptions_FieldNumber_Deprecated, .hasIndex = 1, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBEnumOptions_Storage, deprecated), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBEnumOptions__storage_, deprecated), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1782,29 +1827,32 @@ typedef struct GPBEnumOptions_Storage { .number = GPBEnumOptions_FieldNumber_UninterpretedOptionArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBEnumOptions_Storage, uninterpretedOptionArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBEnumOptions__storage_, uninterpretedOptionArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), + .dataTypeSpecific.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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -1816,18 +1864,18 @@ typedef struct GPBEnumOptions_Storage { @implementation GPBEnumValueOptions @dynamic hasDeprecated, deprecated; -@dynamic uninterpretedOptionArray; +@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count; -typedef struct GPBEnumValueOptions_Storage { +typedef struct GPBEnumValueOptions__storage_ { uint32_t _has_storage_[1]; BOOL deprecated; NSMutableArray *uninterpretedOptionArray; -} GPBEnumValueOptions_Storage; +} GPBEnumValueOptions__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -1835,10 +1883,10 @@ typedef struct GPBEnumValueOptions_Storage { .number = GPBEnumValueOptions_FieldNumber_Deprecated, .hasIndex = 0, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBEnumValueOptions_Storage, deprecated), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBEnumValueOptions__storage_, deprecated), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1846,29 +1894,32 @@ typedef struct GPBEnumValueOptions_Storage { .number = GPBEnumValueOptions_FieldNumber_UninterpretedOptionArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBEnumValueOptions_Storage, uninterpretedOptionArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBEnumValueOptions__storage_, uninterpretedOptionArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), + .dataTypeSpecific.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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -1880,18 +1931,18 @@ typedef struct GPBEnumValueOptions_Storage { @implementation GPBServiceOptions @dynamic hasDeprecated, deprecated; -@dynamic uninterpretedOptionArray; +@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count; -typedef struct GPBServiceOptions_Storage { +typedef struct GPBServiceOptions__storage_ { uint32_t _has_storage_[1]; BOOL deprecated; NSMutableArray *uninterpretedOptionArray; -} GPBServiceOptions_Storage; +} GPBServiceOptions__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -1899,10 +1950,10 @@ typedef struct GPBServiceOptions_Storage { .number = GPBServiceOptions_FieldNumber_Deprecated, .hasIndex = 0, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBServiceOptions_Storage, deprecated), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBServiceOptions__storage_, deprecated), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1910,29 +1961,32 @@ typedef struct GPBServiceOptions_Storage { .number = GPBServiceOptions_FieldNumber_UninterpretedOptionArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBServiceOptions_Storage, uninterpretedOptionArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBServiceOptions__storage_, uninterpretedOptionArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), + .dataTypeSpecific.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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -1944,18 +1998,18 @@ typedef struct GPBServiceOptions_Storage { @implementation GPBMethodOptions @dynamic hasDeprecated, deprecated; -@dynamic uninterpretedOptionArray; +@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count; -typedef struct GPBMethodOptions_Storage { +typedef struct GPBMethodOptions__storage_ { uint32_t _has_storage_[1]; BOOL deprecated; NSMutableArray *uninterpretedOptionArray; -} GPBMethodOptions_Storage; +} GPBMethodOptions__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -1963,10 +2017,10 @@ typedef struct GPBMethodOptions_Storage { .number = GPBMethodOptions_FieldNumber_Deprecated, .hasIndex = 0, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBMethodOptions_Storage, deprecated), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBMethodOptions__storage_, deprecated), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1974,29 +2028,32 @@ typedef struct GPBMethodOptions_Storage { .number = GPBMethodOptions_FieldNumber_UninterpretedOptionArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBMethodOptions_Storage, uninterpretedOptionArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBMethodOptions__storage_, uninterpretedOptionArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), + .dataTypeSpecific.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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -2007,7 +2064,7 @@ typedef struct GPBMethodOptions_Storage { @implementation GPBUninterpretedOption -@dynamic nameArray; +@dynamic nameArray, nameArray_Count; @dynamic hasIdentifierValue, identifierValue; @dynamic hasPositiveIntValue, positiveIntValue; @dynamic hasNegativeIntValue, negativeIntValue; @@ -2015,7 +2072,7 @@ typedef struct GPBMethodOptions_Storage { @dynamic hasStringValue, stringValue; @dynamic hasAggregateValue, aggregateValue; -typedef struct GPBUninterpretedOption_Storage { +typedef struct GPBUninterpretedOption__storage_ { uint32_t _has_storage_[1]; NSMutableArray *nameArray; NSString *identifierValue; @@ -2024,12 +2081,12 @@ typedef struct GPBUninterpretedOption_Storage { uint64_t positiveIntValue; int64_t negativeIntValue; double doubleValue; -} GPBUninterpretedOption_Storage; +} GPBUninterpretedOption__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -2037,10 +2094,10 @@ typedef struct GPBUninterpretedOption_Storage { .number = GPBUninterpretedOption_FieldNumber_NameArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBUninterpretedOption_Storage, nameArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBUninterpretedOption__storage_, nameArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption_NamePart), + .dataTypeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption_NamePart), .fieldOptions = NULL, }, { @@ -2048,10 +2105,10 @@ typedef struct GPBUninterpretedOption_Storage { .number = GPBUninterpretedOption_FieldNumber_IdentifierValue, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBUninterpretedOption_Storage, identifierValue), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBUninterpretedOption__storage_, identifierValue), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -2059,10 +2116,10 @@ typedef struct GPBUninterpretedOption_Storage { .number = GPBUninterpretedOption_FieldNumber_PositiveIntValue, .hasIndex = 2, .flags = GPBFieldOptional, - .type = GPBTypeUInt64, - .offset = offsetof(GPBUninterpretedOption_Storage, positiveIntValue), + .dataType = GPBDataTypeUInt64, + .offset = offsetof(GPBUninterpretedOption__storage_, positiveIntValue), .defaultValue.valueUInt64 = 0ULL, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -2070,10 +2127,10 @@ typedef struct GPBUninterpretedOption_Storage { .number = GPBUninterpretedOption_FieldNumber_NegativeIntValue, .hasIndex = 3, .flags = GPBFieldOptional, - .type = GPBTypeInt64, - .offset = offsetof(GPBUninterpretedOption_Storage, negativeIntValue), + .dataType = GPBDataTypeInt64, + .offset = offsetof(GPBUninterpretedOption__storage_, negativeIntValue), .defaultValue.valueInt64 = 0LL, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -2081,10 +2138,10 @@ typedef struct GPBUninterpretedOption_Storage { .number = GPBUninterpretedOption_FieldNumber_DoubleValue, .hasIndex = 4, .flags = GPBFieldOptional, - .type = GPBTypeDouble, - .offset = offsetof(GPBUninterpretedOption_Storage, doubleValue), + .dataType = GPBDataTypeDouble, + .offset = offsetof(GPBUninterpretedOption__storage_, doubleValue), .defaultValue.valueDouble = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -2092,10 +2149,10 @@ typedef struct GPBUninterpretedOption_Storage { .number = GPBUninterpretedOption_FieldNumber_StringValue, .hasIndex = 5, .flags = GPBFieldOptional, - .type = GPBTypeData, - .offset = offsetof(GPBUninterpretedOption_Storage, stringValue), + .dataType = GPBDataTypeBytes, + .offset = offsetof(GPBUninterpretedOption__storage_, stringValue), .defaultValue.valueData = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -2103,26 +2160,29 @@ typedef struct GPBUninterpretedOption_Storage { .number = GPBUninterpretedOption_FieldNumber_AggregateValue, .hasIndex = 6, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBUninterpretedOption_Storage, aggregateValue), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBUninterpretedOption__storage_, aggregateValue), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -2136,16 +2196,16 @@ typedef struct GPBUninterpretedOption_Storage { @dynamic hasNamePart, namePart; @dynamic hasIsExtension, isExtension; -typedef struct GPBUninterpretedOption_NamePart_Storage { +typedef struct GPBUninterpretedOption_NamePart__storage_ { uint32_t _has_storage_[1]; BOOL isExtension; NSString *namePart; -} GPBUninterpretedOption_NamePart_Storage; +} GPBUninterpretedOption_NamePart__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -2153,10 +2213,10 @@ typedef struct GPBUninterpretedOption_NamePart_Storage { .number = GPBUninterpretedOption_NamePart_FieldNumber_NamePart, .hasIndex = 0, .flags = GPBFieldRequired, - .type = GPBTypeString, - .offset = offsetof(GPBUninterpretedOption_NamePart_Storage, namePart), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBUninterpretedOption_NamePart__storage_, namePart), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -2164,26 +2224,29 @@ typedef struct GPBUninterpretedOption_NamePart_Storage { .number = GPBUninterpretedOption_NamePart_FieldNumber_IsExtension, .hasIndex = 1, .flags = GPBFieldRequired, - .type = GPBTypeBool, - .offset = offsetof(GPBUninterpretedOption_NamePart_Storage, isExtension), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBUninterpretedOption_NamePart__storage_, isExtension), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -2194,17 +2257,17 @@ typedef struct GPBUninterpretedOption_NamePart_Storage { @implementation GPBSourceCodeInfo -@dynamic locationArray; +@dynamic locationArray, locationArray_Count; -typedef struct GPBSourceCodeInfo_Storage { +typedef struct GPBSourceCodeInfo__storage_ { uint32_t _has_storage_[1]; NSMutableArray *locationArray; -} GPBSourceCodeInfo_Storage; +} GPBSourceCodeInfo__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -2212,26 +2275,29 @@ typedef struct GPBSourceCodeInfo_Storage { .number = GPBSourceCodeInfo_FieldNumber_LocationArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBSourceCodeInfo_Storage, locationArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBSourceCodeInfo__storage_, locationArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBSourceCodeInfo_Location), + .dataTypeSpecific.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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -2242,25 +2308,25 @@ typedef struct GPBSourceCodeInfo_Storage { @implementation GPBSourceCodeInfo_Location -@dynamic pathArray; -@dynamic spanArray; +@dynamic pathArray, pathArray_Count; +@dynamic spanArray, spanArray_Count; @dynamic hasLeadingComments, leadingComments; @dynamic hasTrailingComments, trailingComments; -@dynamic leadingDetachedCommentsArray; +@dynamic leadingDetachedCommentsArray, leadingDetachedCommentsArray_Count; -typedef struct GPBSourceCodeInfo_Location_Storage { +typedef struct GPBSourceCodeInfo_Location__storage_ { uint32_t _has_storage_[1]; GPBInt32Array *pathArray; GPBInt32Array *spanArray; NSString *leadingComments; NSString *trailingComments; NSMutableArray *leadingDetachedCommentsArray; -} GPBSourceCodeInfo_Location_Storage; +} GPBSourceCodeInfo_Location__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -2268,10 +2334,10 @@ typedef struct GPBSourceCodeInfo_Location_Storage { .number = GPBSourceCodeInfo_Location_FieldNumber_PathArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated | GPBFieldPacked, - .type = GPBTypeInt32, - .offset = offsetof(GPBSourceCodeInfo_Location_Storage, pathArray), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBSourceCodeInfo_Location__storage_, pathArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, #if GPBOBJC_INCLUDE_FIELD_OPTIONS .fieldOptions = "\000\000\000\002\020\001", #else @@ -2283,10 +2349,10 @@ typedef struct GPBSourceCodeInfo_Location_Storage { .number = GPBSourceCodeInfo_Location_FieldNumber_SpanArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated | GPBFieldPacked, - .type = GPBTypeInt32, - .offset = offsetof(GPBSourceCodeInfo_Location_Storage, spanArray), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBSourceCodeInfo_Location__storage_, spanArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, #if GPBOBJC_INCLUDE_FIELD_OPTIONS .fieldOptions = "\000\000\000\002\020\001", #else @@ -2298,10 +2364,10 @@ typedef struct GPBSourceCodeInfo_Location_Storage { .number = GPBSourceCodeInfo_Location_FieldNumber_LeadingComments, .hasIndex = 2, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBSourceCodeInfo_Location_Storage, leadingComments), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBSourceCodeInfo_Location__storage_, leadingComments), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -2309,10 +2375,10 @@ typedef struct GPBSourceCodeInfo_Location_Storage { .number = GPBSourceCodeInfo_Location_FieldNumber_TrailingComments, .hasIndex = 3, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBSourceCodeInfo_Location_Storage, trailingComments), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBSourceCodeInfo_Location__storage_, trailingComments), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -2320,26 +2386,29 @@ typedef struct GPBSourceCodeInfo_Location_Storage { .number = GPBSourceCodeInfo_Location_FieldNumber_LeadingDetachedCommentsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeString, - .offset = offsetof(GPBSourceCodeInfo_Location_Storage, leadingDetachedCommentsArray), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBSourceCodeInfo_Location__storage_, leadingDetachedCommentsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/Duration.pbobjc.h b/objectivec/google/protobuf/Duration.pbobjc.h index f65df6c9..9ecba197 100644 --- a/objectivec/google/protobuf/Duration.pbobjc.h +++ b/objectivec/google/protobuf/Duration.pbobjc.h @@ -11,6 +11,7 @@ CF_EXTERN_C_BEGIN +NS_ASSUME_NONNULL_BEGIN #pragma mark - GPBDurationRoot @@ -86,6 +87,8 @@ typedef GPB_ENUM(GPBDuration_FieldNumber) { @end +NS_ASSUME_NONNULL_END + CF_EXTERN_C_END // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Duration.pbobjc.m b/objectivec/google/protobuf/Duration.pbobjc.m index 4db030f4..e4fd4951 100644 --- a/objectivec/google/protobuf/Duration.pbobjc.m +++ b/objectivec/google/protobuf/Duration.pbobjc.m @@ -11,11 +11,14 @@ @end +#pragma mark - GPBDurationRoot_FileDescriptor + 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) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -29,16 +32,16 @@ static GPBFileDescriptor *GPBDurationRoot_FileDescriptor(void) { @dynamic seconds; @dynamic nanos; -typedef struct GPBDuration_Storage { +typedef struct GPBDuration__storage_ { uint32_t _has_storage_[1]; int32_t nanos; int64_t seconds; -} GPBDuration_Storage; +} GPBDuration__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -46,10 +49,10 @@ typedef struct GPBDuration_Storage { .number = GPBDuration_FieldNumber_Seconds, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeInt64, - .offset = offsetof(GPBDuration_Storage, seconds), + .dataType = GPBDataTypeInt64, + .offset = offsetof(GPBDuration__storage_, seconds), .defaultValue.valueInt64 = 0LL, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -57,26 +60,29 @@ typedef struct GPBDuration_Storage { .number = GPBDuration_FieldNumber_Nanos, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBDuration_Storage, nanos), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBDuration__storage_, nanos), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/Empty.pbobjc.h b/objectivec/google/protobuf/Empty.pbobjc.h index 1356c3a7..17e2b19b 100644 --- a/objectivec/google/protobuf/Empty.pbobjc.h +++ b/objectivec/google/protobuf/Empty.pbobjc.h @@ -11,6 +11,7 @@ CF_EXTERN_C_BEGIN +NS_ASSUME_NONNULL_BEGIN #pragma mark - GPBEmptyRoot @@ -36,6 +37,8 @@ CF_EXTERN_C_BEGIN @end +NS_ASSUME_NONNULL_END + CF_EXTERN_C_END // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Empty.pbobjc.m b/objectivec/google/protobuf/Empty.pbobjc.m index 619fe905..17f0c1ac 100644 --- a/objectivec/google/protobuf/Empty.pbobjc.m +++ b/objectivec/google/protobuf/Empty.pbobjc.m @@ -11,11 +11,14 @@ @end +#pragma mark - GPBEmptyRoot_FileDescriptor + static GPBFileDescriptor *GPBEmptyRoot_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) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -27,30 +30,31 @@ static GPBFileDescriptor *GPBEmptyRoot_FileDescriptor(void) { @implementation GPBEmpty -typedef struct GPBEmpty_Storage { +typedef struct GPBEmpty__storage_ { uint32_t _has_storage_[0]; -} GPBEmpty_Storage; +} GPBEmpty__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEmpty class] - rootClass:[GPBEmptyRoot class] - file:GPBEmptyRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBEmpty_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBEmpty class] + rootClass:[GPBEmptyRoot class] + file:GPBEmptyRoot_FileDescriptor() + fields:NULL + fieldCount:0 + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBEmpty__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.h b/objectivec/google/protobuf/FieldMask.pbobjc.h index ac6f03d2..de62c03b 100644 --- a/objectivec/google/protobuf/FieldMask.pbobjc.h +++ b/objectivec/google/protobuf/FieldMask.pbobjc.h @@ -11,6 +11,7 @@ CF_EXTERN_C_BEGIN +NS_ASSUME_NONNULL_BEGIN #pragma mark - GPBFieldMaskRoot @@ -151,10 +152,13 @@ typedef GPB_ENUM(GPBFieldMask_FieldNumber) { // The set of field mask paths. // |pathsArray| contains |NSString| -@property(nonatomic, readwrite, strong) NSMutableArray *pathsArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *pathsArray; +@property(nonatomic, readonly) NSUInteger pathsArray_Count; @end +NS_ASSUME_NONNULL_END + CF_EXTERN_C_END // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.m b/objectivec/google/protobuf/FieldMask.pbobjc.m index e37ac6c2..f9684f51 100644 --- a/objectivec/google/protobuf/FieldMask.pbobjc.m +++ b/objectivec/google/protobuf/FieldMask.pbobjc.m @@ -11,11 +11,14 @@ @end +#pragma mark - GPBFieldMaskRoot_FileDescriptor + static GPBFileDescriptor *GPBFieldMaskRoot_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) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -26,17 +29,17 @@ static GPBFileDescriptor *GPBFieldMaskRoot_FileDescriptor(void) { @implementation GPBFieldMask -@dynamic pathsArray; +@dynamic pathsArray, pathsArray_Count; -typedef struct GPBFieldMask_Storage { +typedef struct GPBFieldMask__storage_ { uint32_t _has_storage_[1]; NSMutableArray *pathsArray; -} GPBFieldMask_Storage; +} GPBFieldMask__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -44,26 +47,29 @@ typedef struct GPBFieldMask_Storage { .number = GPBFieldMask_FieldNumber_PathsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeString, - .offset = offsetof(GPBFieldMask_Storage, pathsArray), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFieldMask__storage_, pathsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFieldMask class] - rootClass:[GPBFieldMaskRoot class] - file:GPBFieldMaskRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBFieldMask_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBFieldMask class] + rootClass:[GPBFieldMaskRoot class] + file:GPBFieldMaskRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBFieldMask__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/SourceContext.pbobjc.h b/objectivec/google/protobuf/SourceContext.pbobjc.h index bcbf1e3d..6bc57149 100644 --- a/objectivec/google/protobuf/SourceContext.pbobjc.h +++ b/objectivec/google/protobuf/SourceContext.pbobjc.h @@ -11,6 +11,7 @@ CF_EXTERN_C_BEGIN +NS_ASSUME_NONNULL_BEGIN #pragma mark - GPBSourceContextRoot @@ -35,10 +36,12 @@ typedef GPB_ENUM(GPBSourceContext_FieldNumber) { // The path-qualified name of the .proto file that contained the associated // protobuf element. For example: `"google/protobuf/source.proto"`. -@property(nonatomic, readwrite, copy) NSString *fileName; +@property(nonatomic, readwrite, copy, null_resettable) NSString *fileName; @end +NS_ASSUME_NONNULL_END + CF_EXTERN_C_END // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/SourceContext.pbobjc.m b/objectivec/google/protobuf/SourceContext.pbobjc.m index 271f9243..ac1827fc 100644 --- a/objectivec/google/protobuf/SourceContext.pbobjc.m +++ b/objectivec/google/protobuf/SourceContext.pbobjc.m @@ -11,11 +11,14 @@ @end +#pragma mark - GPBSourceContextRoot_FileDescriptor + static GPBFileDescriptor *GPBSourceContextRoot_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) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -28,15 +31,15 @@ static GPBFileDescriptor *GPBSourceContextRoot_FileDescriptor(void) { @dynamic fileName; -typedef struct GPBSourceContext_Storage { +typedef struct GPBSourceContext__storage_ { uint32_t _has_storage_[1]; NSString *fileName; -} GPBSourceContext_Storage; +} GPBSourceContext__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -44,26 +47,29 @@ typedef struct GPBSourceContext_Storage { .number = GPBSourceContext_FieldNumber_FileName, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBSourceContext_Storage, fileName), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBSourceContext__storage_, fileName), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBSourceContext class] - rootClass:[GPBSourceContextRoot class] - file:GPBSourceContextRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBSourceContext_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBSourceContext class] + rootClass:[GPBSourceContextRoot class] + file:GPBSourceContextRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBSourceContext__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/Struct.pbobjc.h b/objectivec/google/protobuf/Struct.pbobjc.h index f55af82b..d72f9738 100644 --- a/objectivec/google/protobuf/Struct.pbobjc.h +++ b/objectivec/google/protobuf/Struct.pbobjc.h @@ -14,6 +14,8 @@ CF_EXTERN_C_BEGIN @class GPBListValue; @class GPBStruct; +NS_ASSUME_NONNULL_BEGIN + #pragma mark - Enum GPBNullValue // `NullValue` is a singleton enumeration to represent the null @@ -28,7 +30,6 @@ GPBEnumDescriptor *GPBNullValue_EnumDescriptor(void); BOOL GPBNullValue_IsValidValue(int32_t value); - #pragma mark - GPBStructRoot @interface GPBStructRoot : GPBRootObject @@ -56,7 +57,8 @@ typedef GPB_ENUM(GPBStruct_FieldNumber) { // Map of dynamically typed values. // |fields| values are |GPBValue| -@property(nonatomic, readwrite, strong) NSMutableDictionary *fields; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableDictionary *fields; +@property(nonatomic, readonly) NSUInteger fields_Count; @end @@ -96,16 +98,16 @@ typedef GPB_ENUM(GPBValue_Kind_OneOfCase) { @property(nonatomic, readwrite) double numberValue; // Represents a string value. -@property(nonatomic, readwrite, copy) NSString *stringValue; +@property(nonatomic, readwrite, copy, null_resettable) NSString *stringValue; // Represents a boolean value. @property(nonatomic, readwrite) BOOL boolValue; // Represents a structured value. -@property(nonatomic, readwrite, strong) GPBStruct *structValue; +@property(nonatomic, readwrite, strong, null_resettable) GPBStruct *structValue; // Represents a repeated `Value`. -@property(nonatomic, readwrite, strong) GPBListValue *listValue; +@property(nonatomic, readwrite, strong, null_resettable) GPBListValue *listValue; @end @@ -125,10 +127,13 @@ typedef GPB_ENUM(GPBListValue_FieldNumber) { // Repeated field of dynamically typed values. // |valuesArray| contains |GPBValue| -@property(nonatomic, readwrite, strong) NSMutableArray *valuesArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *valuesArray; +@property(nonatomic, readonly) NSUInteger valuesArray_Count; @end +NS_ASSUME_NONNULL_END + CF_EXTERN_C_END // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Struct.pbobjc.m b/objectivec/google/protobuf/Struct.pbobjc.m index e5a8b547..14b8f271 100644 --- a/objectivec/google/protobuf/Struct.pbobjc.m +++ b/objectivec/google/protobuf/Struct.pbobjc.m @@ -11,11 +11,14 @@ @end +#pragma mark - GPBStructRoot_FileDescriptor + static GPBFileDescriptor *GPBStructRoot_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) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -51,17 +54,17 @@ BOOL GPBNullValue_IsValidValue(int32_t value__) { @implementation GPBStruct -@dynamic fields; +@dynamic fields, fields_Count; -typedef struct GPBStruct_Storage { +typedef struct GPBStruct__storage_ { uint32_t _has_storage_[1]; NSMutableDictionary *fields; -} GPBStruct_Storage; +} GPBStruct__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -69,26 +72,29 @@ typedef struct GPBStruct_Storage { .number = GPBStruct_FieldNumber_Fields, .hasIndex = GPBNoHasBit, .flags = GPBFieldMapKeyString, - .type = GPBTypeMessage, - .offset = offsetof(GPBStruct_Storage, fields), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBStruct__storage_, fields), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBValue), + .dataTypeSpecific.className = GPBStringifySymbol(GPBValue), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBStruct class] - rootClass:[GPBStructRoot class] - file:GPBStructRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBStruct_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBStruct class] + rootClass:[GPBStructRoot class] + file:GPBStructRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBStruct__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -107,7 +113,7 @@ typedef struct GPBStruct_Storage { @dynamic structValue; @dynamic listValue; -typedef struct GPBValue_Storage { +typedef struct GPBValue__storage_ { uint32_t _has_storage_[2]; BOOL boolValue; GPBNullValue nullValue; @@ -115,12 +121,12 @@ typedef struct GPBValue_Storage { GPBStruct *structValue; GPBListValue *listValue; double numberValue; -} GPBValue_Storage; +} GPBValue__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageOneofDescription oneofs[] = { { @@ -134,10 +140,10 @@ typedef struct GPBValue_Storage { .number = GPBValue_FieldNumber_NullValue, .hasIndex = -1, .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, - .type = GPBTypeEnum, - .offset = offsetof(GPBValue_Storage, nullValue), + .dataType = GPBDataTypeEnum, + .offset = offsetof(GPBValue__storage_, nullValue), .defaultValue.valueEnum = GPBNullValue_NullValue, - .typeSpecific.enumDescFunc = GPBNullValue_EnumDescriptor, + .dataTypeSpecific.enumDescFunc = GPBNullValue_EnumDescriptor, .fieldOptions = NULL, }, { @@ -145,10 +151,10 @@ typedef struct GPBValue_Storage { .number = GPBValue_FieldNumber_NumberValue, .hasIndex = -1, .flags = GPBFieldOptional, - .type = GPBTypeDouble, - .offset = offsetof(GPBValue_Storage, numberValue), + .dataType = GPBDataTypeDouble, + .offset = offsetof(GPBValue__storage_, numberValue), .defaultValue.valueDouble = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -156,10 +162,10 @@ typedef struct GPBValue_Storage { .number = GPBValue_FieldNumber_StringValue, .hasIndex = -1, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBValue_Storage, stringValue), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBValue__storage_, stringValue), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -167,10 +173,10 @@ typedef struct GPBValue_Storage { .number = GPBValue_FieldNumber_BoolValue, .hasIndex = -1, .flags = GPBFieldOptional, - .type = GPBTypeBool, - .offset = offsetof(GPBValue_Storage, boolValue), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBValue__storage_, boolValue), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -178,10 +184,10 @@ typedef struct GPBValue_Storage { .number = GPBValue_FieldNumber_StructValue, .hasIndex = -1, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBValue_Storage, structValue), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBValue__storage_, structValue), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBStruct), + .dataTypeSpecific.className = GPBStringifySymbol(GPBStruct), .fieldOptions = NULL, }, { @@ -189,26 +195,29 @@ typedef struct GPBValue_Storage { .number = GPBValue_FieldNumber_ListValue, .hasIndex = -1, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBValue_Storage, listValue), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBValue__storage_, listValue), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBListValue), + .dataTypeSpecific.className = GPBStringifySymbol(GPBListValue), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBValue class] - rootClass:[GPBStructRoot class] - file:GPBStructRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:oneofs - oneofCount:sizeof(oneofs) / sizeof(GPBMessageOneofDescription) - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBValue_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBValue class] + rootClass:[GPBStructRoot class] + file:GPBStructRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:oneofs + oneofCount:sizeof(oneofs) / sizeof(GPBMessageOneofDescription) + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBValue__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -218,7 +227,7 @@ typedef struct GPBValue_Storage { int32_t GPBValue_NullValue_RawValue(GPBValue *message) { GPBDescriptor *descriptor = [GPBValue descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue]; - return GPBGetInt32IvarWithField(message, field); + return GPBGetMessageInt32Field(message, field); } void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value) { @@ -236,17 +245,17 @@ void GPBValue_ClearKindOneOfCase(GPBValue *message) { @implementation GPBListValue -@dynamic valuesArray; +@dynamic valuesArray, valuesArray_Count; -typedef struct GPBListValue_Storage { +typedef struct GPBListValue__storage_ { uint32_t _has_storage_[1]; NSMutableArray *valuesArray; -} GPBListValue_Storage; +} GPBListValue__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -254,26 +263,29 @@ typedef struct GPBListValue_Storage { .number = GPBListValue_FieldNumber_ValuesArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBListValue_Storage, valuesArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBListValue__storage_, valuesArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBValue), + .dataTypeSpecific.className = GPBStringifySymbol(GPBValue), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBListValue class] - rootClass:[GPBStructRoot class] - file:GPBStructRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBListValue_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBListValue class] + rootClass:[GPBStructRoot class] + file:GPBStructRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBListValue__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.h b/objectivec/google/protobuf/Timestamp.pbobjc.h index a81321b4..0b342156 100644 --- a/objectivec/google/protobuf/Timestamp.pbobjc.h +++ b/objectivec/google/protobuf/Timestamp.pbobjc.h @@ -11,6 +11,7 @@ CF_EXTERN_C_BEGIN +NS_ASSUME_NONNULL_BEGIN #pragma mark - GPBTimestampRoot @@ -97,6 +98,8 @@ typedef GPB_ENUM(GPBTimestamp_FieldNumber) { @end +NS_ASSUME_NONNULL_END + CF_EXTERN_C_END // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.m b/objectivec/google/protobuf/Timestamp.pbobjc.m index 197dff48..a206f159 100644 --- a/objectivec/google/protobuf/Timestamp.pbobjc.m +++ b/objectivec/google/protobuf/Timestamp.pbobjc.m @@ -11,11 +11,14 @@ @end +#pragma mark - GPBTimestampRoot_FileDescriptor + 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) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -29,16 +32,16 @@ static GPBFileDescriptor *GPBTimestampRoot_FileDescriptor(void) { @dynamic seconds; @dynamic nanos; -typedef struct GPBTimestamp_Storage { +typedef struct GPBTimestamp__storage_ { uint32_t _has_storage_[1]; int32_t nanos; int64_t seconds; -} GPBTimestamp_Storage; +} GPBTimestamp__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -46,10 +49,10 @@ typedef struct GPBTimestamp_Storage { .number = GPBTimestamp_FieldNumber_Seconds, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeInt64, - .offset = offsetof(GPBTimestamp_Storage, seconds), + .dataType = GPBDataTypeInt64, + .offset = offsetof(GPBTimestamp__storage_, seconds), .defaultValue.valueInt64 = 0LL, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -57,26 +60,29 @@ typedef struct GPBTimestamp_Storage { .number = GPBTimestamp_FieldNumber_Nanos, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBTimestamp_Storage, nanos), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBTimestamp__storage_, nanos), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.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]; + GPBDescriptor *localDescriptor = + [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]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/Type.pbobjc.h b/objectivec/google/protobuf/Type.pbobjc.h index 652a33a7..eb807ae5 100644 --- a/objectivec/google/protobuf/Type.pbobjc.h +++ b/objectivec/google/protobuf/Type.pbobjc.h @@ -14,6 +14,8 @@ CF_EXTERN_C_BEGIN @class GPBAny; @class GPBSourceContext; +NS_ASSUME_NONNULL_BEGIN + #pragma mark - Enum GPBField_Kind // Kind represents a basic field type. @@ -101,7 +103,6 @@ GPBEnumDescriptor *GPBField_Cardinality_EnumDescriptor(void); BOOL GPBField_Cardinality_IsValidValue(int32_t value); - #pragma mark - GPBTypeRoot @interface GPBTypeRoot : GPBRootObject @@ -127,24 +128,27 @@ typedef GPB_ENUM(GPBType_FieldNumber) { @interface GPBType : GPBMessage // The fully qualified message name. -@property(nonatomic, readwrite, copy) NSString *name; +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; // The list of fields. // |fieldsArray| contains |GPBField| -@property(nonatomic, readwrite, strong) NSMutableArray *fieldsArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *fieldsArray; +@property(nonatomic, readonly) NSUInteger fieldsArray_Count; // The list of oneof definitions. // The list of oneofs declared in this Type // |oneofsArray| contains |NSString| -@property(nonatomic, readwrite, strong) NSMutableArray *oneofsArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *oneofsArray; +@property(nonatomic, readonly) NSUInteger oneofsArray_Count; // The proto options. // |optionsArray| contains |GPBOption| -@property(nonatomic, readwrite, strong) NSMutableArray *optionsArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +@property(nonatomic, readonly) NSUInteger optionsArray_Count; // The source context. @property(nonatomic, readwrite) BOOL hasSourceContext; -@property(nonatomic, readwrite, strong) GPBSourceContext *sourceContext; +@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext; @end @@ -174,11 +178,11 @@ typedef GPB_ENUM(GPBField_FieldNumber) { @property(nonatomic, readwrite) int32_t number; // The field name. -@property(nonatomic, readwrite, copy) NSString *name; +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; // The type URL (without the scheme) when the type is MESSAGE or ENUM, // such as `type.googleapis.com/google.protobuf.Empty`. -@property(nonatomic, readwrite, copy) NSString *typeURL; +@property(nonatomic, readwrite, copy, null_resettable) NSString *typeURL; // Index in Type.oneofs. Starts at 1. Zero means no oneof mapping. @property(nonatomic, readwrite) int32_t oneofIndex; @@ -188,7 +192,8 @@ typedef GPB_ENUM(GPBField_FieldNumber) { // The proto options. // |optionsArray| contains |GPBOption| -@property(nonatomic, readwrite, strong) NSMutableArray *optionsArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +@property(nonatomic, readonly) NSUInteger optionsArray_Count; @end @@ -211,19 +216,21 @@ typedef GPB_ENUM(GPBEnum_FieldNumber) { @interface GPBEnum : GPBMessage // Enum type name. -@property(nonatomic, readwrite, copy) NSString *name; +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; // Enum value definitions. // |enumvalueArray| contains |GPBEnumValue| -@property(nonatomic, readwrite, strong) NSMutableArray *enumvalueArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *enumvalueArray; +@property(nonatomic, readonly) NSUInteger enumvalueArray_Count; // Proto options for the enum type. // |optionsArray| contains |GPBOption| -@property(nonatomic, readwrite, strong) NSMutableArray *optionsArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +@property(nonatomic, readonly) NSUInteger optionsArray_Count; // The source context. @property(nonatomic, readwrite) BOOL hasSourceContext; -@property(nonatomic, readwrite, strong) GPBSourceContext *sourceContext; +@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext; @end @@ -239,14 +246,15 @@ typedef GPB_ENUM(GPBEnumValue_FieldNumber) { @interface GPBEnumValue : GPBMessage // Enum value name. -@property(nonatomic, readwrite, copy) NSString *name; +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; // Enum value number. @property(nonatomic, readwrite) int32_t number; // Proto options for the enum value. // |optionsArray| contains |GPBOption| -@property(nonatomic, readwrite, strong) NSMutableArray *optionsArray; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +@property(nonatomic, readonly) NSUInteger optionsArray_Count; @end @@ -261,14 +269,16 @@ typedef GPB_ENUM(GPBOption_FieldNumber) { @interface GPBOption : GPBMessage // Proto option name. -@property(nonatomic, readwrite, copy) NSString *name; +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; // Proto option value. @property(nonatomic, readwrite) BOOL hasValue; -@property(nonatomic, readwrite, strong) GPBAny *value; +@property(nonatomic, readwrite, strong, null_resettable) GPBAny *value; @end +NS_ASSUME_NONNULL_END + CF_EXTERN_C_END // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Type.pbobjc.m b/objectivec/google/protobuf/Type.pbobjc.m index 182370c8..5a2ce282 100644 --- a/objectivec/google/protobuf/Type.pbobjc.m +++ b/objectivec/google/protobuf/Type.pbobjc.m @@ -16,10 +16,8 @@ // about thread safety and initialization of registry. static GPBExtensionRegistry* registry = nil; if (!registry) { + GPBDebugCheckRuntimeVersion(); registry = [[GPBExtensionRegistry alloc] init]; - static GPBExtensionDescription descriptions[] = { - }; - #pragma unused (descriptions) [registry addExtensions:[GPBAnyRoot extensionRegistry]]; [registry addExtensions:[GPBSourceContextRoot extensionRegistry]]; } @@ -28,11 +26,14 @@ @end +#pragma mark - GPBTypeRoot_FileDescriptor + static GPBFileDescriptor *GPBTypeRoot_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) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -44,24 +45,24 @@ static GPBFileDescriptor *GPBTypeRoot_FileDescriptor(void) { @implementation GPBType @dynamic name; -@dynamic fieldsArray; -@dynamic oneofsArray; -@dynamic optionsArray; +@dynamic fieldsArray, fieldsArray_Count; +@dynamic oneofsArray, oneofsArray_Count; +@dynamic optionsArray, optionsArray_Count; @dynamic hasSourceContext, sourceContext; -typedef struct GPBType_Storage { +typedef struct GPBType__storage_ { uint32_t _has_storage_[1]; NSString *name; NSMutableArray *fieldsArray; NSMutableArray *oneofsArray; NSMutableArray *optionsArray; GPBSourceContext *sourceContext; -} GPBType_Storage; +} GPBType__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -69,10 +70,10 @@ typedef struct GPBType_Storage { .number = GPBType_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBType_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBType__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -80,10 +81,10 @@ typedef struct GPBType_Storage { .number = GPBType_FieldNumber_FieldsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBType_Storage, fieldsArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBType__storage_, fieldsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBField), + .dataTypeSpecific.className = GPBStringifySymbol(GPBField), .fieldOptions = NULL, }, { @@ -91,10 +92,10 @@ typedef struct GPBType_Storage { .number = GPBType_FieldNumber_OneofsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeString, - .offset = offsetof(GPBType_Storage, oneofsArray), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBType__storage_, oneofsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -102,10 +103,10 @@ typedef struct GPBType_Storage { .number = GPBType_FieldNumber_OptionsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBType_Storage, optionsArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBType__storage_, optionsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), .fieldOptions = NULL, }, { @@ -113,26 +114,29 @@ typedef struct GPBType_Storage { .number = GPBType_FieldNumber_SourceContext, .hasIndex = 4, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBType_Storage, sourceContext), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBType__storage_, sourceContext), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBSourceContext), + .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBType class] - rootClass:[GPBTypeRoot class] - file:GPBTypeRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBType_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBType class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBType__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -150,9 +154,9 @@ typedef struct GPBType_Storage { @dynamic typeURL; @dynamic oneofIndex; @dynamic packed; -@dynamic optionsArray; +@dynamic optionsArray, optionsArray_Count; -typedef struct GPBField_Storage { +typedef struct GPBField__storage_ { uint32_t _has_storage_[1]; BOOL packed; GPBField_Kind kind; @@ -162,12 +166,12 @@ typedef struct GPBField_Storage { NSString *name; NSString *typeURL; NSMutableArray *optionsArray; -} GPBField_Storage; +} GPBField__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -175,10 +179,10 @@ typedef struct GPBField_Storage { .number = GPBField_FieldNumber_Kind, .hasIndex = 0, .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, - .type = GPBTypeEnum, - .offset = offsetof(GPBField_Storage, kind), + .dataType = GPBDataTypeEnum, + .offset = offsetof(GPBField__storage_, kind), .defaultValue.valueEnum = GPBField_Kind_TypeUnknown, - .typeSpecific.enumDescFunc = GPBField_Kind_EnumDescriptor, + .dataTypeSpecific.enumDescFunc = GPBField_Kind_EnumDescriptor, .fieldOptions = NULL, }, { @@ -186,10 +190,10 @@ typedef struct GPBField_Storage { .number = GPBField_FieldNumber_Cardinality, .hasIndex = 1, .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, - .type = GPBTypeEnum, - .offset = offsetof(GPBField_Storage, cardinality), + .dataType = GPBDataTypeEnum, + .offset = offsetof(GPBField__storage_, cardinality), .defaultValue.valueEnum = GPBField_Cardinality_CardinalityUnknown, - .typeSpecific.enumDescFunc = GPBField_Cardinality_EnumDescriptor, + .dataTypeSpecific.enumDescFunc = GPBField_Cardinality_EnumDescriptor, .fieldOptions = NULL, }, { @@ -197,10 +201,10 @@ typedef struct GPBField_Storage { .number = GPBField_FieldNumber_Number, .hasIndex = 2, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBField_Storage, number), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBField__storage_, number), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -208,10 +212,10 @@ typedef struct GPBField_Storage { .number = GPBField_FieldNumber_Name, .hasIndex = 3, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBField_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBField__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -219,10 +223,10 @@ typedef struct GPBField_Storage { .number = GPBField_FieldNumber_TypeURL, .hasIndex = 4, .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom, - .type = GPBTypeString, - .offset = offsetof(GPBField_Storage, typeURL), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBField__storage_, typeURL), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -230,10 +234,10 @@ typedef struct GPBField_Storage { .number = GPBField_FieldNumber_OneofIndex, .hasIndex = 5, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBField_Storage, oneofIndex), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBField__storage_, oneofIndex), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -241,10 +245,10 @@ typedef struct GPBField_Storage { .number = GPBField_FieldNumber_Packed, .hasIndex = 6, .flags = GPBFieldOptional, - .type = GPBTypeBool, - .offset = offsetof(GPBField_Storage, packed), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBField__storage_, packed), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -252,10 +256,10 @@ typedef struct GPBField_Storage { .number = GPBField_FieldNumber_OptionsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBField_Storage, optionsArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBField__storage_, optionsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), .fieldOptions = NULL, }, }; @@ -268,20 +272,23 @@ typedef struct GPBField_Storage { #else static const char *extraTextFormatInfo = "\001\006\004\241!!\000"; #endif // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBField class] - rootClass:[GPBTypeRoot class] - file:GPBTypeRoot_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(GPBField_Storage) - wireFormat:NO - extraTextFormatInfo:extraTextFormatInfo]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBField class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_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(GPBField__storage_) + wireFormat:NO + extraTextFormatInfo:extraTextFormatInfo]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -291,7 +298,7 @@ typedef struct GPBField_Storage { int32_t GPBField_Kind_RawValue(GPBField *message) { GPBDescriptor *descriptor = [GPBField descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind]; - return GPBGetInt32IvarWithField(message, field); + return GPBGetMessageInt32Field(message, field); } void SetGPBField_Kind_RawValue(GPBField *message, int32_t value) { @@ -303,7 +310,7 @@ void SetGPBField_Kind_RawValue(GPBField *message, int32_t value) { int32_t GPBField_Cardinality_RawValue(GPBField *message) { GPBDescriptor *descriptor = [GPBField descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality]; - return GPBGetInt32IvarWithField(message, field); + return GPBGetMessageInt32Field(message, field); } void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value) { @@ -407,22 +414,22 @@ BOOL GPBField_Cardinality_IsValidValue(int32_t value__) { @implementation GPBEnum @dynamic name; -@dynamic enumvalueArray; -@dynamic optionsArray; +@dynamic enumvalueArray, enumvalueArray_Count; +@dynamic optionsArray, optionsArray_Count; @dynamic hasSourceContext, sourceContext; -typedef struct GPBEnum_Storage { +typedef struct GPBEnum__storage_ { uint32_t _has_storage_[1]; NSString *name; NSMutableArray *enumvalueArray; NSMutableArray *optionsArray; GPBSourceContext *sourceContext; -} GPBEnum_Storage; +} GPBEnum__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -430,10 +437,10 @@ typedef struct GPBEnum_Storage { .number = GPBEnum_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBEnum_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBEnum__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -441,10 +448,10 @@ typedef struct GPBEnum_Storage { .number = GPBEnum_FieldNumber_EnumvalueArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBEnum_Storage, enumvalueArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBEnum__storage_, enumvalueArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBEnumValue), + .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumValue), .fieldOptions = NULL, }, { @@ -452,10 +459,10 @@ typedef struct GPBEnum_Storage { .number = GPBEnum_FieldNumber_OptionsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBEnum_Storage, optionsArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBEnum__storage_, optionsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), .fieldOptions = NULL, }, { @@ -463,26 +470,29 @@ typedef struct GPBEnum_Storage { .number = GPBEnum_FieldNumber_SourceContext, .hasIndex = 3, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBEnum_Storage, sourceContext), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBEnum__storage_, sourceContext), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBSourceContext), + .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnum class] - rootClass:[GPBTypeRoot class] - file:GPBTypeRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBEnum_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBEnum class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBEnum__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -495,19 +505,19 @@ typedef struct GPBEnum_Storage { @dynamic name; @dynamic number; -@dynamic optionsArray; +@dynamic optionsArray, optionsArray_Count; -typedef struct GPBEnumValue_Storage { +typedef struct GPBEnumValue__storage_ { uint32_t _has_storage_[1]; int32_t number; NSString *name; NSMutableArray *optionsArray; -} GPBEnumValue_Storage; +} GPBEnumValue__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -515,10 +525,10 @@ typedef struct GPBEnumValue_Storage { .number = GPBEnumValue_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBEnumValue_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBEnumValue__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -526,10 +536,10 @@ typedef struct GPBEnumValue_Storage { .number = GPBEnumValue_FieldNumber_Number, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBEnumValue_Storage, number), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBEnumValue__storage_, number), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -537,26 +547,29 @@ typedef struct GPBEnumValue_Storage { .number = GPBEnumValue_FieldNumber_OptionsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBEnumValue_Storage, optionsArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBEnumValue__storage_, optionsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnumValue class] - rootClass:[GPBTypeRoot class] - file:GPBTypeRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBEnumValue_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBEnumValue class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBEnumValue__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -570,16 +583,16 @@ typedef struct GPBEnumValue_Storage { @dynamic name; @dynamic hasValue, value; -typedef struct GPBOption_Storage { +typedef struct GPBOption__storage_ { uint32_t _has_storage_[1]; NSString *name; GPBAny *value; -} GPBOption_Storage; +} GPBOption__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -587,10 +600,10 @@ typedef struct GPBOption_Storage { .number = GPBOption_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBOption_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBOption__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -598,26 +611,29 @@ typedef struct GPBOption_Storage { .number = GPBOption_FieldNumber_Value, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBOption_Storage, value), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBOption__storage_, value), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBAny), + .dataTypeSpecific.className = GPBStringifySymbol(GPBAny), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBOption class] - rootClass:[GPBTypeRoot class] - file:GPBTypeRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBOption_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBOption class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBOption__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/Wrappers.pbobjc.h b/objectivec/google/protobuf/Wrappers.pbobjc.h index 227d958e..b4718d02 100644 --- a/objectivec/google/protobuf/Wrappers.pbobjc.h +++ b/objectivec/google/protobuf/Wrappers.pbobjc.h @@ -11,6 +11,7 @@ CF_EXTERN_C_BEGIN +NS_ASSUME_NONNULL_BEGIN #pragma mark - GPBWrappersRoot @@ -131,7 +132,7 @@ typedef GPB_ENUM(GPBStringValue_FieldNumber) { @interface GPBStringValue : GPBMessage // The string value. -@property(nonatomic, readwrite, copy) NSString *value; +@property(nonatomic, readwrite, copy, null_resettable) NSString *value; @end @@ -145,10 +146,12 @@ typedef GPB_ENUM(GPBBytesValue_FieldNumber) { @interface GPBBytesValue : GPBMessage // The bytes value. -@property(nonatomic, readwrite, copy) NSData *value; +@property(nonatomic, readwrite, copy, null_resettable) NSData *value; @end +NS_ASSUME_NONNULL_END + CF_EXTERN_C_END // @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Wrappers.pbobjc.m b/objectivec/google/protobuf/Wrappers.pbobjc.m index 6c342850..0403b464 100644 --- a/objectivec/google/protobuf/Wrappers.pbobjc.m +++ b/objectivec/google/protobuf/Wrappers.pbobjc.m @@ -11,11 +11,14 @@ @end +#pragma mark - GPBWrappersRoot_FileDescriptor + static GPBFileDescriptor *GPBWrappersRoot_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) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -28,15 +31,15 @@ static GPBFileDescriptor *GPBWrappersRoot_FileDescriptor(void) { @dynamic value; -typedef struct GPBDoubleValue_Storage { +typedef struct GPBDoubleValue__storage_ { uint32_t _has_storage_[1]; double value; -} GPBDoubleValue_Storage; +} GPBDoubleValue__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -44,26 +47,29 @@ typedef struct GPBDoubleValue_Storage { .number = GPBDoubleValue_FieldNumber_Value, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeDouble, - .offset = offsetof(GPBDoubleValue_Storage, value), + .dataType = GPBDataTypeDouble, + .offset = offsetof(GPBDoubleValue__storage_, value), .defaultValue.valueDouble = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBDoubleValue class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBDoubleValue_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBDoubleValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBDoubleValue__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -76,15 +82,15 @@ typedef struct GPBDoubleValue_Storage { @dynamic value; -typedef struct GPBFloatValue_Storage { +typedef struct GPBFloatValue__storage_ { uint32_t _has_storage_[1]; float value; -} GPBFloatValue_Storage; +} GPBFloatValue__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -92,26 +98,29 @@ typedef struct GPBFloatValue_Storage { .number = GPBFloatValue_FieldNumber_Value, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeFloat, - .offset = offsetof(GPBFloatValue_Storage, value), + .dataType = GPBDataTypeFloat, + .offset = offsetof(GPBFloatValue__storage_, value), .defaultValue.valueFloat = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFloatValue class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBFloatValue_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBFloatValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBFloatValue__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -124,15 +133,15 @@ typedef struct GPBFloatValue_Storage { @dynamic value; -typedef struct GPBInt64Value_Storage { +typedef struct GPBInt64Value__storage_ { uint32_t _has_storage_[1]; int64_t value; -} GPBInt64Value_Storage; +} GPBInt64Value__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -140,26 +149,29 @@ typedef struct GPBInt64Value_Storage { .number = GPBInt64Value_FieldNumber_Value, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeInt64, - .offset = offsetof(GPBInt64Value_Storage, value), + .dataType = GPBDataTypeInt64, + .offset = offsetof(GPBInt64Value__storage_, value), .defaultValue.valueInt64 = 0LL, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBInt64Value class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBInt64Value_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBInt64Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBInt64Value__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -172,15 +184,15 @@ typedef struct GPBInt64Value_Storage { @dynamic value; -typedef struct GPBUInt64Value_Storage { +typedef struct GPBUInt64Value__storage_ { uint32_t _has_storage_[1]; uint64_t value; -} GPBUInt64Value_Storage; +} GPBUInt64Value__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -188,26 +200,29 @@ typedef struct GPBUInt64Value_Storage { .number = GPBUInt64Value_FieldNumber_Value, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeUInt64, - .offset = offsetof(GPBUInt64Value_Storage, value), + .dataType = GPBDataTypeUInt64, + .offset = offsetof(GPBUInt64Value__storage_, value), .defaultValue.valueUInt64 = 0ULL, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBUInt64Value class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBUInt64Value_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBUInt64Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBUInt64Value__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -220,15 +235,15 @@ typedef struct GPBUInt64Value_Storage { @dynamic value; -typedef struct GPBInt32Value_Storage { +typedef struct GPBInt32Value__storage_ { uint32_t _has_storage_[1]; int32_t value; -} GPBInt32Value_Storage; +} GPBInt32Value__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -236,26 +251,29 @@ typedef struct GPBInt32Value_Storage { .number = GPBInt32Value_FieldNumber_Value, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBInt32Value_Storage, value), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBInt32Value__storage_, value), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBInt32Value class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBInt32Value_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBInt32Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBInt32Value__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -268,15 +286,15 @@ typedef struct GPBInt32Value_Storage { @dynamic value; -typedef struct GPBUInt32Value_Storage { +typedef struct GPBUInt32Value__storage_ { uint32_t _has_storage_[1]; uint32_t value; -} GPBUInt32Value_Storage; +} GPBUInt32Value__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -284,26 +302,29 @@ typedef struct GPBUInt32Value_Storage { .number = GPBUInt32Value_FieldNumber_Value, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeUInt32, - .offset = offsetof(GPBUInt32Value_Storage, value), + .dataType = GPBDataTypeUInt32, + .offset = offsetof(GPBUInt32Value__storage_, value), .defaultValue.valueUInt32 = 0U, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBUInt32Value class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBUInt32Value_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBUInt32Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBUInt32Value__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -316,15 +337,15 @@ typedef struct GPBUInt32Value_Storage { @dynamic value; -typedef struct GPBBoolValue_Storage { +typedef struct GPBBoolValue__storage_ { uint32_t _has_storage_[1]; BOOL value; -} GPBBoolValue_Storage; +} GPBBoolValue__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -332,26 +353,29 @@ typedef struct GPBBoolValue_Storage { .number = GPBBoolValue_FieldNumber_Value, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeBool, - .offset = offsetof(GPBBoolValue_Storage, value), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBBoolValue__storage_, value), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBBoolValue class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBBoolValue_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBBoolValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBBoolValue__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -364,15 +388,15 @@ typedef struct GPBBoolValue_Storage { @dynamic value; -typedef struct GPBStringValue_Storage { +typedef struct GPBStringValue__storage_ { uint32_t _has_storage_[1]; NSString *value; -} GPBStringValue_Storage; +} GPBStringValue__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -380,26 +404,29 @@ typedef struct GPBStringValue_Storage { .number = GPBStringValue_FieldNumber_Value, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBStringValue_Storage, value), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBStringValue__storage_, value), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBStringValue class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBStringValue_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBStringValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBStringValue__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -412,15 +439,15 @@ typedef struct GPBStringValue_Storage { @dynamic value; -typedef struct GPBBytesValue_Storage { +typedef struct GPBBytesValue__storage_ { uint32_t _has_storage_[1]; NSData *value; -} GPBBytesValue_Storage; +} GPBBytesValue__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -428,26 +455,29 @@ typedef struct GPBBytesValue_Storage { .number = GPBBytesValue_FieldNumber_Value, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeData, - .offset = offsetof(GPBBytesValue_Storage, value), + .dataType = GPBDataTypeBytes, + .offset = offsetof(GPBBytesValue__storage_, value), .defaultValue.valueData = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBBytesValue class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBBytesValue_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBBytesValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBBytesValue__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/ruby/ext/google/protobuf_c/defs.c b/ruby/ext/google/protobuf_c/defs.c index e3341cca..8f9f33e2 100644 --- a/ruby/ext/google/protobuf_c/defs.c +++ b/ruby/ext/google/protobuf_c/defs.c @@ -546,11 +546,9 @@ upb_fieldtype_t ruby_to_fieldtype(VALUE type) { rb_raise(rb_eArgError, "Expected symbol for field type."); } - upb_fieldtype_t upb_type = -1; - #define CONVERT(upb, ruby) \ if (SYM2ID(type) == rb_intern( # ruby )) { \ - upb_type = UPB_TYPE_ ## upb; \ + return UPB_TYPE_ ## upb; \ } CONVERT(FLOAT, float); @@ -567,11 +565,8 @@ upb_fieldtype_t ruby_to_fieldtype(VALUE type) { #undef CONVERT - if (upb_type == -1) { - rb_raise(rb_eArgError, "Unknown field type."); - } - - return upb_type; + rb_raise(rb_eArgError, "Unknown field type."); + return 0; } VALUE fieldtype_to_ruby(upb_fieldtype_t type) { @@ -666,10 +661,12 @@ VALUE FieldDescriptor_label_set(VALUE _self, VALUE label) { } upb_label_t upb_label = -1; + bool converted = false; #define CONVERT(upb, ruby) \ if (SYM2ID(label) == rb_intern( # ruby )) { \ upb_label = UPB_LABEL_ ## upb; \ + converted = true; \ } CONVERT(OPTIONAL, optional); @@ -678,7 +675,7 @@ VALUE FieldDescriptor_label_set(VALUE _self, VALUE label) { #undef CONVERT - if (upb_label == -1) { + if (!converted) { rb_raise(rb_eArgError, "Unknown field label."); } diff --git a/ruby/ext/google/protobuf_c/extconf.rb b/ruby/ext/google/protobuf_c/extconf.rb index 74203b07..b368dcc6 100644 --- a/ruby/ext/google/protobuf_c/extconf.rb +++ b/ruby/ext/google/protobuf_c/extconf.rb @@ -2,9 +2,7 @@ require 'mkmf' -$CFLAGS += " -O3 -std=c99 -Wno-unused-function " + - "-Wno-declaration-after-statement -Wno-unused-variable " + - "-Wno-sign-compare -DNDEBUG " +$CFLAGS += " -std=c99 -O3 -DNDEBUG" $objs = ["protobuf.o", "defs.o", "storage.o", "message.o", "repeated_field.o", "map.o", "encode_decode.o", "upb.o"] diff --git a/ruby/ext/google/protobuf_c/map.c b/ruby/ext/google/protobuf_c/map.c index 12e7a9d9..3436e09a 100644 --- a/ruby/ext/google/protobuf_c/map.c +++ b/ruby/ext/google/protobuf_c/map.c @@ -120,7 +120,7 @@ static VALUE table_key_to_ruby(Map* self, const char* buf, size_t length) { } static void* value_memory(upb_value* v) { - return (void*)(&v->val.uint64); + return (void*)(&v->val); } // ----------------------------------------------------------------------------- diff --git a/ruby/ext/google/protobuf_c/upb.c b/ruby/ext/google/protobuf_c/upb.c index 55a99cfe..f99c7a70 100644 --- a/ruby/ext/google/protobuf_c/upb.c +++ b/ruby/ext/google/protobuf_c/upb.c @@ -13,7 +13,7 @@ typedef struct { size_t len; - char str[1]; // Null-terminated string data follows. + char str[1]; /* Null-terminated string data follows. */ } str_t; static str_t *newstr(const char *data, size_t len) { @@ -27,7 +27,7 @@ static str_t *newstr(const char *data, size_t len) { static void freestr(str_t *s) { free(s); } -// isalpha() etc. from <ctype.h> are locale-dependent, which we don't want. +/* isalpha() etc. from <ctype.h> are locale-dependent, which we don't want. */ static bool upb_isbetween(char c, char low, char high) { return c >= low && c <= high; } @@ -42,7 +42,8 @@ static bool upb_isalphanum(char c) { static bool upb_isident(const char *str, size_t len, bool full, upb_status *s) { bool start = true; - for (size_t i = 0; i < len; i++) { + size_t i; + for (i = 0; i < len; i++) { char c = str[i]; if (c == '.') { if (start || !full) { @@ -87,39 +88,22 @@ bool upb_def_setfullname(upb_def *def, const char *fullname, upb_status *s) { upb_def *upb_def_dup(const upb_def *def, const void *o) { switch (def->type) { case UPB_DEF_MSG: - return UPB_UPCAST(upb_msgdef_dup(upb_downcast_msgdef(def), o)); + return upb_msgdef_upcast_mutable( + upb_msgdef_dup(upb_downcast_msgdef(def), o)); case UPB_DEF_FIELD: - return UPB_UPCAST(upb_fielddef_dup(upb_downcast_fielddef(def), o)); + return upb_fielddef_upcast_mutable( + upb_fielddef_dup(upb_downcast_fielddef(def), o)); case UPB_DEF_ENUM: - return UPB_UPCAST(upb_enumdef_dup(upb_downcast_enumdef(def), o)); + return upb_enumdef_upcast_mutable( + upb_enumdef_dup(upb_downcast_enumdef(def), o)); default: assert(false); return NULL; } } -bool upb_def_isfrozen(const upb_def *def) { - return upb_refcounted_isfrozen(UPB_UPCAST(def)); -} - -void upb_def_ref(const upb_def *def, const void *owner) { - upb_refcounted_ref(UPB_UPCAST(def), owner); -} - -void upb_def_unref(const upb_def *def, const void *owner) { - upb_refcounted_unref(UPB_UPCAST(def), owner); -} - -void upb_def_donateref(const upb_def *def, const void *from, const void *to) { - upb_refcounted_donateref(UPB_UPCAST(def), from, to); -} - -void upb_def_checkref(const upb_def *def, const void *owner) { - upb_refcounted_checkref(UPB_UPCAST(def), owner); -} - static bool upb_def_init(upb_def *def, upb_deftype_t type, const struct upb_refcounted_vtbl *vtbl, const void *owner) { - if (!upb_refcounted_init(UPB_UPCAST(def), vtbl, owner)) return false; + if (!upb_refcounted_init(upb_def_upcast_mutable(def), vtbl, owner)) return false; def->type = type; def->fullname = NULL; def->came_from_user = false; @@ -131,7 +115,7 @@ static void upb_def_uninit(upb_def *def) { } static const char *msgdef_name(const upb_msgdef *m) { - const char *name = upb_def_fullname(UPB_UPCAST(m)); + const char *name = upb_def_fullname(upb_msgdef_upcast(m)); return name ? name : "(anonymous)"; } @@ -154,13 +138,15 @@ static bool upb_validate_field(upb_fielddef *f, upb_status *s) { } if (upb_fielddef_hassubdef(f)) { + const upb_def *subdef; + if (f->subdef_is_symbolic) { upb_status_seterrf(s, "field '%s.%s' has not been resolved", msgdef_name(f->msg.def), upb_fielddef_name(f)); return false; } - const upb_def *subdef = upb_fielddef_subdef(f); + subdef = upb_fielddef_subdef(f); if (subdef == NULL) { upb_status_seterrf(s, "field %s.%s is missing required subdef", msgdef_name(f->msg.def), upb_fielddef_name(f)); @@ -179,14 +165,14 @@ static bool upb_validate_field(upb_fielddef *f, upb_status *s) { bool has_default_name = upb_fielddef_enumhasdefaultstr(f); bool has_default_number = upb_fielddef_enumhasdefaultint32(f); - // Previously verified by upb_validate_enumdef(). + /* Previously verified by upb_validate_enumdef(). */ assert(upb_enumdef_numvals(upb_fielddef_enumsubdef(f)) > 0); - // We've already validated that we have an associated enumdef and that it - // has at least one member, so at least one of these should be true. - // Because if the user didn't set anything, we'll pick up the enum's - // default, but if the user *did* set something we should at least pick up - // the one they set (int32 or string). + /* We've already validated that we have an associated enumdef and that it + * has at least one member, so at least one of these should be true. + * Because if the user didn't set anything, we'll pick up the enum's + * default, but if the user *did* set something we should at least pick up + * the one they set (int32 or string). */ assert(has_default_name || has_default_number); if (!has_default_name) { @@ -205,13 +191,13 @@ static bool upb_validate_field(upb_fielddef *f, upb_status *s) { return false; } - // Lift the effective numeric default into the field's default slot, in case - // we were only getting it "by reference" from the enumdef. + /* Lift the effective numeric default into the field's default slot, in case + * we were only getting it "by reference" from the enumdef. */ upb_fielddef_setdefaultint32(f, upb_fielddef_defaultint32(f)); } - // Ensure that MapEntry submessages only appear as repeated fields, not - // optional/required (singular) fields. + /* Ensure that MapEntry submessages only appear as repeated fields, not + * optional/required (singular) fields. */ if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE && upb_fielddef_msgsubdef(f) != NULL) { const upb_msgdef *subdef = upb_fielddef_msgsubdef(f); @@ -238,8 +224,8 @@ static bool upb_validate_enumdef(const upb_enumdef *e, upb_status *s) { return true; } -// All submessage fields are lower than all other fields. -// Secondly, fields are increasing in order. +/* All submessage fields are lower than all other fields. + * Secondly, fields are increasing in order. */ uint32_t field_rank(const upb_fielddef *f) { uint32_t ret = upb_fielddef_number(f); const uint32_t high_bit = 1 << 30; @@ -256,14 +242,15 @@ int cmp_fields(const void *p1, const void *p2) { } static bool assign_msg_indices(upb_msgdef *m, upb_status *s) { - // Sort fields. upb internally relies on UPB_TYPE_MESSAGE fields having the - // lowest indexes, but we do not publicly guarantee this. + /* Sort fields. upb internally relies on UPB_TYPE_MESSAGE fields having the + * lowest indexes, but we do not publicly guarantee this. */ + upb_msg_field_iter j; + int i; + uint32_t selector; int n = upb_msgdef_numfields(m); upb_fielddef **fields = malloc(n * sizeof(*fields)); if (!fields) return false; - upb_msg_field_iter j; - int i; m->submsg_field_count = 0; for(i = 0, upb_msg_field_begin(&j, m); !upb_msg_field_done(&j); @@ -282,7 +269,7 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) { qsort(fields, n, sizeof(*fields), cmp_fields); - uint32_t selector = UPB_STATIC_SELECTOR_COUNT + m->submsg_field_count; + selector = UPB_STATIC_SELECTOR_COUNT + m->submsg_field_count; for (i = 0; i < n; i++) { upb_fielddef *f = fields[i]; f->index_ = i; @@ -292,38 +279,42 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) { m->selector_count = selector; #ifndef NDEBUG - // Verify that all selectors for the message are distinct. - // + { + /* Verify that all selectors for the message are distinct. */ #define TRY(type) \ - if (upb_handlers_getselector(f, type, &sel)) upb_inttable_insert(&t, sel, v); + if (upb_handlers_getselector(f, type, &sel)) upb_inttable_insert(&t, sel, v); - upb_inttable t; - upb_inttable_init(&t, UPB_CTYPE_BOOL); - upb_value v = upb_value_bool(true); - upb_selector_t sel; - upb_inttable_insert(&t, UPB_STARTMSG_SELECTOR, v); - upb_inttable_insert(&t, UPB_ENDMSG_SELECTOR, v); - for(upb_msg_field_begin(&j, m); - !upb_msg_field_done(&j); - upb_msg_field_next(&j)) { - upb_fielddef *f = upb_msg_iter_field(&j); - // These calls will assert-fail in upb_table if the value already exists. - TRY(UPB_HANDLER_INT32); - TRY(UPB_HANDLER_INT64) - TRY(UPB_HANDLER_UINT32) - TRY(UPB_HANDLER_UINT64) - TRY(UPB_HANDLER_FLOAT) - TRY(UPB_HANDLER_DOUBLE) - TRY(UPB_HANDLER_BOOL) - TRY(UPB_HANDLER_STARTSTR) - TRY(UPB_HANDLER_STRING) - TRY(UPB_HANDLER_ENDSTR) - TRY(UPB_HANDLER_STARTSUBMSG) - TRY(UPB_HANDLER_ENDSUBMSG) - TRY(UPB_HANDLER_STARTSEQ) - TRY(UPB_HANDLER_ENDSEQ) - } - upb_inttable_uninit(&t); + upb_inttable t; + upb_value v; + upb_selector_t sel; + + upb_inttable_init(&t, UPB_CTYPE_BOOL); + v = upb_value_bool(true); + upb_inttable_insert(&t, UPB_STARTMSG_SELECTOR, v); + upb_inttable_insert(&t, UPB_ENDMSG_SELECTOR, v); + for(upb_msg_field_begin(&j, m); + !upb_msg_field_done(&j); + upb_msg_field_next(&j)) { + upb_fielddef *f = upb_msg_iter_field(&j); + /* These calls will assert-fail in upb_table if the value already + * exists. */ + TRY(UPB_HANDLER_INT32); + TRY(UPB_HANDLER_INT64) + TRY(UPB_HANDLER_UINT32) + TRY(UPB_HANDLER_UINT64) + TRY(UPB_HANDLER_FLOAT) + TRY(UPB_HANDLER_DOUBLE) + TRY(UPB_HANDLER_BOOL) + TRY(UPB_HANDLER_STARTSTR) + TRY(UPB_HANDLER_STRING) + TRY(UPB_HANDLER_ENDSTR) + TRY(UPB_HANDLER_STARTSUBMSG) + TRY(UPB_HANDLER_ENDSUBMSG) + TRY(UPB_HANDLER_STARTSEQ) + TRY(UPB_HANDLER_ENDSEQ) + } + upb_inttable_uninit(&t); + } #undef TRY #endif @@ -332,14 +323,17 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) { } bool upb_def_freeze(upb_def *const* defs, int n, upb_status *s) { + int i; + int maxdepth; + bool ret; upb_status_clear(s); - // First perform validation, in two passes so we can check that we have a - // transitive closure without needing to search. - for (int i = 0; i < n; i++) { + /* First perform validation, in two passes so we can check that we have a + * transitive closure without needing to search. */ + for (i = 0; i < n; i++) { upb_def *def = defs[i]; if (upb_def_isfrozen(def)) { - // Could relax this requirement if it's annoying. + /* Could relax this requirement if it's annoying. */ upb_status_seterrmsg(s, "def is already frozen"); goto err; } else if (def->type == UPB_DEF_FIELD) { @@ -350,14 +344,14 @@ bool upb_def_freeze(upb_def *const* defs, int n, upb_status *s) { goto err; } } else { - // Set now to detect transitive closure in the second pass. + /* Set now to detect transitive closure in the second pass. */ def->came_from_user = true; } } - // Second pass of validation. Also assign selector bases and indexes, and - // compact tables. - for (int i = 0; i < n; i++) { + /* Second pass of validation. Also assign selector bases and indexes, and + * compact tables. */ + for (i = 0; i < n; i++) { upb_msgdef *m = upb_dyncast_msgdef_mutable(defs[i]); upb_enumdef *e = upb_dyncast_enumdef_mutable(defs[i]); if (m) { @@ -370,17 +364,17 @@ bool upb_def_freeze(upb_def *const* defs, int n, upb_status *s) { } } - // Def graph contains FieldDefs between each MessageDef, so double the limit. - int maxdepth = UPB_MAX_MESSAGE_DEPTH * 2; + /* Def graph contains FieldDefs between each MessageDef, so double the + * limit. */ + maxdepth = UPB_MAX_MESSAGE_DEPTH * 2; - // Validation all passed; freeze the defs. - bool ret = - upb_refcounted_freeze((upb_refcounted * const *)defs, n, s, maxdepth); + /* Validation all passed; freeze the defs. */ + ret = upb_refcounted_freeze((upb_refcounted * const *)defs, n, s, maxdepth); assert(!(s && ret != upb_ok(s))); return ret; err: - for (int i = 0; i < n; i++) { + for (i = 0; i < n; i++) { defs[i]->came_from_user = false; } assert(!(s && upb_ok(s))); @@ -395,12 +389,12 @@ static void upb_enumdef_free(upb_refcounted *r) { upb_inttable_iter i; upb_inttable_begin(&i, &e->iton); for( ; !upb_inttable_done(&i); upb_inttable_next(&i)) { - // To clean up the upb_strdup() from upb_enumdef_addval(). + /* To clean up the upb_strdup() from upb_enumdef_addval(). */ free(upb_value_getcstr(upb_inttable_iter_value(&i))); } upb_strtable_uninit(&e->ntoi); upb_inttable_uninit(&e->iton); - upb_def_uninit(UPB_UPCAST(e)); + upb_def_uninit(upb_enumdef_upcast_mutable(e)); free(e); } @@ -408,7 +402,8 @@ upb_enumdef *upb_enumdef_new(const void *owner) { static const struct upb_refcounted_vtbl vtbl = {NULL, &upb_enumdef_free}; upb_enumdef *e = malloc(sizeof(*e)); if (!e) return NULL; - if (!upb_def_init(UPB_UPCAST(e), UPB_DEF_ENUM, &vtbl, owner)) goto err2; + if (!upb_def_init(upb_enumdef_upcast_mutable(e), UPB_DEF_ENUM, &vtbl, owner)) + goto err2; if (!upb_strtable_init(&e->ntoi, UPB_CTYPE_INT32)) goto err2; if (!upb_inttable_init(&e->iton, UPB_CTYPE_CSTR)) goto err1; return e; @@ -421,9 +416,9 @@ err2: } upb_enumdef *upb_enumdef_dup(const upb_enumdef *e, const void *owner) { + upb_enum_iter i; upb_enumdef *new_e = upb_enumdef_new(owner); if (!new_e) return NULL; - upb_enum_iter i; for(upb_enum_begin(&i, e); !upb_enum_done(&i); upb_enum_next(&i)) { bool success = upb_enumdef_addval( new_e, upb_enum_iter_name(&i),upb_enum_iter_number(&i), NULL); @@ -435,39 +430,18 @@ upb_enumdef *upb_enumdef_dup(const upb_enumdef *e, const void *owner) { return new_e; } -bool upb_enumdef_isfrozen(const upb_enumdef *e) { - return upb_def_isfrozen(UPB_UPCAST(e)); -} - -void upb_enumdef_ref(const upb_enumdef *e, const void *owner) { - upb_def_ref(UPB_UPCAST(e), owner); -} - -void upb_enumdef_unref(const upb_enumdef *e, const void *owner) { - upb_def_unref(UPB_UPCAST(e), owner); -} - -void upb_enumdef_donateref( - const upb_enumdef *e, const void *from, const void *to) { - upb_def_donateref(UPB_UPCAST(e), from, to); -} - -void upb_enumdef_checkref(const upb_enumdef *e, const void *owner) { - upb_def_checkref(UPB_UPCAST(e), owner); -} - bool upb_enumdef_freeze(upb_enumdef *e, upb_status *status) { - upb_def *d = UPB_UPCAST(e); + upb_def *d = upb_enumdef_upcast_mutable(e); return upb_def_freeze(&d, 1, status); } const char *upb_enumdef_fullname(const upb_enumdef *e) { - return upb_def_fullname(UPB_UPCAST(e)); + return upb_def_fullname(upb_enumdef_upcast(e)); } bool upb_enumdef_setfullname(upb_enumdef *e, const char *fullname, upb_status *s) { - return upb_def_setfullname(UPB_UPCAST(e), fullname, s); + return upb_def_setfullname(upb_enumdef_upcast_mutable(e), fullname, s); } bool upb_enumdef_addval(upb_enumdef *e, const char *name, int32_t num, @@ -516,7 +490,7 @@ int upb_enumdef_numvals(const upb_enumdef *e) { } void upb_enum_begin(upb_enum_iter *i, const upb_enumdef *e) { - // We iterate over the ntoi table, to account for duplicate numbers. + /* We iterate over the ntoi table, to account for duplicate numbers. */ upb_strtable_begin(i, &e->ntoi); } @@ -561,13 +535,13 @@ static void visitfield(const upb_refcounted *r, upb_refcounted_visit *visit, void *closure) { const upb_fielddef *f = (const upb_fielddef*)r; if (upb_fielddef_containingtype(f)) { - visit(r, UPB_UPCAST2(upb_fielddef_containingtype(f)), closure); + visit(r, upb_msgdef_upcast2(upb_fielddef_containingtype(f)), closure); } if (upb_fielddef_containingoneof(f)) { - visit(r, UPB_UPCAST2(upb_fielddef_containingoneof(f)), closure); + visit(r, upb_oneofdef_upcast2(upb_fielddef_containingoneof(f)), closure); } if (upb_fielddef_subdef(f)) { - visit(r, UPB_UPCAST(upb_fielddef_subdef(f)), closure); + visit(r, upb_def_upcast(upb_fielddef_subdef(f)), closure); } } @@ -576,26 +550,27 @@ static void freefield(upb_refcounted *r) { upb_fielddef_uninit_default(f); if (f->subdef_is_symbolic) free(f->sub.name); - upb_def_uninit(UPB_UPCAST(f)); + upb_def_uninit(upb_fielddef_upcast_mutable(f)); free(f); } static const char *enumdefaultstr(const upb_fielddef *f) { + const upb_enumdef *e; assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM); - const upb_enumdef *e = upb_fielddef_enumsubdef(f); + e = upb_fielddef_enumsubdef(f); if (f->default_is_string && f->defaultval.bytes) { - // Default was explicitly set as a string. + /* Default was explicitly set as a string. */ str_t *s = f->defaultval.bytes; return s->str; } else if (e) { if (!f->default_is_string) { - // Default was explicitly set as an integer; look it up in enumdef. + /* Default was explicitly set as an integer; look it up in enumdef. */ const char *name = upb_enumdef_iton(e, f->defaultval.sint); if (name) { return name; } } else { - // Default is completely unset; pull enumdef default. + /* Default is completely unset; pull enumdef default. */ if (upb_enumdef_numvals(e) > 0) { const char *name = upb_enumdef_iton(e, upb_enumdef_default(e)); assert(name); @@ -607,21 +582,22 @@ static const char *enumdefaultstr(const upb_fielddef *f) { } static bool enumdefaultint32(const upb_fielddef *f, int32_t *val) { + const upb_enumdef *e; assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM); - const upb_enumdef *e = upb_fielddef_enumsubdef(f); + e = upb_fielddef_enumsubdef(f); if (!f->default_is_string) { - // Default was explicitly set as an integer. + /* Default was explicitly set as an integer. */ *val = f->defaultval.sint; return true; } else if (e) { if (f->defaultval.bytes) { - // Default was explicitly set as a str; try to lookup corresponding int. + /* Default was explicitly set as a str; try to lookup corresponding int. */ str_t *s = f->defaultval.bytes; if (upb_enumdef_ntoiz(e, s->str, val)) { return true; } } else { - // Default is unset; try to pull in enumdef default. + /* Default is unset; try to pull in enumdef default. */ if (upb_enumdef_numvals(e) > 0) { *val = upb_enumdef_default(e); return true; @@ -631,11 +607,11 @@ static bool enumdefaultint32(const upb_fielddef *f, int32_t *val) { return false; } -upb_fielddef *upb_fielddef_new(const void *owner) { +upb_fielddef *upb_fielddef_new(const void *o) { static const struct upb_refcounted_vtbl vtbl = {visitfield, freefield}; upb_fielddef *f = malloc(sizeof(*f)); if (!f) return NULL; - if (!upb_def_init(UPB_UPCAST(f), UPB_DEF_FIELD, &vtbl, owner)) { + if (!upb_def_init(upb_fielddef_upcast_mutable(f), UPB_DEF_FIELD, &vtbl, o)) { free(f); return NULL; } @@ -653,19 +629,20 @@ upb_fielddef *upb_fielddef_new(const void *owner) { f->lazy_ = false; f->packed_ = true; - // For the moment we default this to UPB_INTFMT_VARIABLE, since it will work - // with all integer types and is in some since more "default" since the most - // normal-looking proto2 types int32/int64/uint32/uint64 use variable. - // - // Other options to consider: - // - there is no default; users must set this manually (like type). - // - default signed integers to UPB_INTFMT_ZIGZAG, since it's more likely to - // be an optimal default for signed integers. + /* For the moment we default this to UPB_INTFMT_VARIABLE, since it will work + * with all integer types and is in some since more "default" since the most + * normal-looking proto2 types int32/int64/uint32/uint64 use variable. + * + * Other options to consider: + * - there is no default; users must set this manually (like type). + * - default signed integers to UPB_INTFMT_ZIGZAG, since it's more likely to + * be an optimal default for signed integers. */ f->intfmt = UPB_INTFMT_VARIABLE; return f; } upb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner) { + const char *srcname; upb_fielddef *newf = upb_fielddef_new(owner); if (!newf) return NULL; upb_fielddef_settype(newf, upb_fielddef_type(f)); @@ -680,9 +657,8 @@ upb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner) { newf->defaultval = f->defaultval; } - const char *srcname; if (f->subdef_is_symbolic) { - srcname = f->sub.name; // Might be NULL. + srcname = f->sub.name; /* Might be NULL. */ } else { srcname = f->sub.def ? upb_def_fullname(f->sub.def) : NULL; } @@ -701,27 +677,6 @@ upb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner) { return newf; } -bool upb_fielddef_isfrozen(const upb_fielddef *f) { - return upb_def_isfrozen(UPB_UPCAST(f)); -} - -void upb_fielddef_ref(const upb_fielddef *f, const void *owner) { - upb_def_ref(UPB_UPCAST(f), owner); -} - -void upb_fielddef_unref(const upb_fielddef *f, const void *owner) { - upb_def_unref(UPB_UPCAST(f), owner); -} - -void upb_fielddef_donateref( - const upb_fielddef *f, const void *from, const void *to) { - upb_def_donateref(UPB_UPCAST(f), from, to); -} - -void upb_fielddef_checkref(const upb_fielddef *f, const void *owner) { - upb_def_checkref(UPB_UPCAST(f), owner); -} - bool upb_fielddef_typeisset(const upb_fielddef *f) { return f->type_is_set_; } @@ -764,7 +719,7 @@ bool upb_fielddef_packed(const upb_fielddef *f) { } const char *upb_fielddef_name(const upb_fielddef *f) { - return upb_def_fullname(UPB_UPCAST(f)); + return upb_def_fullname(upb_fielddef_upcast(f)); } const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) { @@ -794,8 +749,8 @@ bool upb_fielddef_setcontainingtypename(upb_fielddef *f, const char *name, upb_status_seterrmsg(s, "field has already been added to a message."); return false; } - // TODO: validate name (upb_isident() doesn't quite work atm because this name - // may have a leading "."). + /* TODO: validate name (upb_isident() doesn't quite work atm because this name + * may have a leading "."). */ release_containingtype(f); f->msg.name = upb_strdup(name); f->msg_is_symbolic = true; @@ -807,7 +762,7 @@ bool upb_fielddef_setname(upb_fielddef *f, const char *name, upb_status *s) { upb_status_seterrmsg(s, "Already added to message or oneof"); return false; } - return upb_def_setfullname(UPB_UPCAST(f), name, s); + return upb_def_setfullname(upb_fielddef_upcast_mutable(f), name, s); } static void chkdefaulttype(const upb_fielddef *f, upb_fieldtype_t type) { @@ -867,7 +822,7 @@ const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) { if (upb_fielddef_type(f) == UPB_TYPE_ENUM) { const char *ret = enumdefaultstr(f); assert(ret); - // Enum defaults can't have embedded NULLs. + /* Enum defaults can't have embedded NULLs. */ if (len) *len = strlen(ret); return ret; } @@ -898,7 +853,7 @@ static void upb_fielddef_init_default(upb_fielddef *f) { break; case UPB_TYPE_MESSAGE: break; case UPB_TYPE_ENUM: - // This is our special sentinel that indicates "not set" for an enum. + /* This is our special sentinel that indicates "not set" for an enum. */ f->default_is_string = true; f->defaultval.bytes = NULL; break; @@ -1144,6 +1099,7 @@ void upb_fielddef_setdefaultdouble(upb_fielddef *f, double value) { bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len, upb_status *s) { + str_t *str2; assert(upb_fielddef_isstring(f) || f->type_ == UPB_TYPE_ENUM); if (f->type_ == UPB_TYPE_ENUM && !upb_isident(str, len, false, s)) return false; @@ -1156,7 +1112,7 @@ bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len, assert(f->type_ == UPB_TYPE_ENUM); } - str_t *str2 = newstr(str, len); + str2 = newstr(str, len); f->defaultval.bytes = str2; f->default_is_string = true; return true; @@ -1169,8 +1125,8 @@ void upb_fielddef_setdefaultcstr(upb_fielddef *f, const char *str, } bool upb_fielddef_enumhasdefaultint32(const upb_fielddef *f) { - assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM); int32_t val; + assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM); return enumdefaultint32(f, &val); } @@ -1217,12 +1173,12 @@ bool upb_fielddef_setsubdef(upb_fielddef *f, const upb_def *subdef, bool upb_fielddef_setmsgsubdef(upb_fielddef *f, const upb_msgdef *subdef, upb_status *s) { - return upb_fielddef_setsubdef(f, UPB_UPCAST(subdef), s); + return upb_fielddef_setsubdef(f, upb_msgdef_upcast(subdef), s); } bool upb_fielddef_setenumsubdef(upb_fielddef *f, const upb_enumdef *subdef, upb_status *s) { - return upb_fielddef_setsubdef(f, UPB_UPCAST(subdef), s); + return upb_fielddef_setsubdef(f, upb_enumdef_upcast(subdef), s); } bool upb_fielddef_setsubdefname(upb_fielddef *f, const char *name, @@ -1232,8 +1188,8 @@ bool upb_fielddef_setsubdefname(upb_fielddef *f, const char *name, upb_status_seterrmsg(s, "field type does not accept a subdef"); return false; } - // TODO: validate name (upb_isident() doesn't quite work atm because this name - // may have a leading "."). + /* TODO: validate name (upb_isident() doesn't quite work atm because this name + * may have a leading "."). */ release_subdef(f); f->sub.name = upb_strdup(name); f->subdef_is_symbolic = true; @@ -1282,20 +1238,20 @@ bool upb_fielddef_checkdescriptortype(int32_t type) { static void visitmsg(const upb_refcounted *r, upb_refcounted_visit *visit, void *closure) { + upb_msg_oneof_iter o; const upb_msgdef *m = (const upb_msgdef*)r; upb_msg_field_iter i; for(upb_msg_field_begin(&i, m); !upb_msg_field_done(&i); upb_msg_field_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); - visit(r, UPB_UPCAST2(f), closure); + visit(r, upb_fielddef_upcast2(f), closure); } - upb_msg_oneof_iter o; for(upb_msg_oneof_begin(&o, m); !upb_msg_oneof_done(&o); upb_msg_oneof_next(&o)) { upb_oneofdef *f = upb_msg_iter_oneof(&o); - visit(r, UPB_UPCAST2(f), closure); + visit(r, upb_oneofdef_upcast2(f), closure); } } @@ -1304,7 +1260,7 @@ static void freemsg(upb_refcounted *r) { upb_strtable_uninit(&m->ntoo); upb_strtable_uninit(&m->ntof); upb_inttable_uninit(&m->itof); - upb_def_uninit(UPB_UPCAST(m)); + upb_def_uninit(upb_msgdef_upcast_mutable(m)); free(m); } @@ -1312,7 +1268,8 @@ upb_msgdef *upb_msgdef_new(const void *owner) { static const struct upb_refcounted_vtbl vtbl = {visitmsg, freemsg}; upb_msgdef *m = malloc(sizeof(*m)); if (!m) return NULL; - if (!upb_def_init(UPB_UPCAST(m), UPB_DEF_MSG, &vtbl, owner)) goto err2; + if (!upb_def_init(upb_msgdef_upcast_mutable(m), UPB_DEF_MSG, &vtbl, owner)) + goto err2; if (!upb_inttable_init(&m->itof, UPB_CTYPE_PTR)) goto err3; if (!upb_strtable_init(&m->ntof, UPB_CTYPE_PTR)) goto err2; if (!upb_strtable_init(&m->ntoo, UPB_CTYPE_PTR)) goto err1; @@ -1329,25 +1286,28 @@ err3: } upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner) { + bool ok; + upb_msg_field_iter i; + upb_msg_oneof_iter o; + upb_msgdef *newm = upb_msgdef_new(owner); if (!newm) return NULL; - bool ok = upb_def_setfullname(UPB_UPCAST(newm), - upb_def_fullname(UPB_UPCAST(m)), NULL); + ok = upb_def_setfullname(upb_msgdef_upcast_mutable(newm), + upb_def_fullname(upb_msgdef_upcast(m)), + NULL); newm->map_entry = m->map_entry; UPB_ASSERT_VAR(ok, ok); - upb_msg_field_iter i; for(upb_msg_field_begin(&i, m); !upb_msg_field_done(&i); upb_msg_field_next(&i)) { upb_fielddef *f = upb_fielddef_dup(upb_msg_iter_field(&i), &f); - // Fields in oneofs are dup'd below. + /* Fields in oneofs are dup'd below. */ if (upb_fielddef_containingoneof(f)) continue; if (!f || !upb_msgdef_addfield(newm, f, &f, NULL)) { upb_msgdef_unref(newm, owner); return NULL; } } - upb_msg_oneof_iter o; for(upb_msg_oneof_begin(&o, m); !upb_msg_oneof_done(&o); upb_msg_oneof_next(&o)) { @@ -1360,43 +1320,22 @@ upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner) { return newm; } -bool upb_msgdef_isfrozen(const upb_msgdef *m) { - return upb_def_isfrozen(UPB_UPCAST(m)); -} - -void upb_msgdef_ref(const upb_msgdef *m, const void *owner) { - upb_def_ref(UPB_UPCAST(m), owner); -} - -void upb_msgdef_unref(const upb_msgdef *m, const void *owner) { - upb_def_unref(UPB_UPCAST(m), owner); -} - -void upb_msgdef_donateref( - const upb_msgdef *m, const void *from, const void *to) { - upb_def_donateref(UPB_UPCAST(m), from, to); -} - -void upb_msgdef_checkref(const upb_msgdef *m, const void *owner) { - upb_def_checkref(UPB_UPCAST(m), owner); -} - bool upb_msgdef_freeze(upb_msgdef *m, upb_status *status) { - upb_def *d = UPB_UPCAST(m); + upb_def *d = upb_msgdef_upcast_mutable(m); return upb_def_freeze(&d, 1, status); } const char *upb_msgdef_fullname(const upb_msgdef *m) { - return upb_def_fullname(UPB_UPCAST(m)); + return upb_def_fullname(upb_msgdef_upcast(m)); } bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname, upb_status *s) { - return upb_def_setfullname(UPB_UPCAST(m), fullname, s); + return upb_def_setfullname(upb_msgdef_upcast_mutable(m), fullname, s); } -// Helper: check that the field |f| is safe to add to msgdef |m|. Set an error -// on status |s| and return false if not. +/* Helper: check that the field |f| is safe to add to msgdef |m|. Set an error + * on status |s| and return false if not. */ static bool check_field_add(const upb_msgdef *m, const upb_fielddef *f, upb_status *s) { if (upb_fielddef_containingtype(f) != NULL) { @@ -1426,40 +1365,42 @@ static void add_field(upb_msgdef *m, upb_fielddef *f, const void *ref_donor) { bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor, upb_status *s) { - // TODO: extensions need to have a separate namespace, because proto2 allows a - // top-level extension (ie. one not in any package) to have the same name as a - // field from the message. - // - // This also implies that there needs to be a separate lookup-by-name method - // for extensions. It seems desirable for iteration to return both extensions - // and non-extensions though. - // - // We also need to validate that the field number is in an extension range iff - // it is an extension. - - // This method is idempotent. Check if |f| is already part of this msgdef and - // return immediately if so. + /* TODO: extensions need to have a separate namespace, because proto2 allows a + * top-level extension (ie. one not in any package) to have the same name as a + * field from the message. + * + * This also implies that there needs to be a separate lookup-by-name method + * for extensions. It seems desirable for iteration to return both extensions + * and non-extensions though. + * + * We also need to validate that the field number is in an extension range iff + * it is an extension. + * + * This method is idempotent. Check if |f| is already part of this msgdef and + * return immediately if so. */ if (upb_fielddef_containingtype(f) == m) { return true; } - // Check constraints for all fields before performing any action. + /* Check constraints for all fields before performing any action. */ if (!check_field_add(m, f, s)) { return false; } else if (upb_fielddef_containingoneof(f) != NULL) { - // Fields in a oneof can only be added by adding the oneof to the msgdef. + /* Fields in a oneof can only be added by adding the oneof to the msgdef. */ upb_status_seterrmsg(s, "fielddef is part of a oneof"); return false; } - // Constraint checks ok, perform the action. + /* Constraint checks ok, perform the action. */ add_field(m, f, ref_donor); return true; } bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor, upb_status *s) { - // Check various conditions that would prevent this oneof from being added. + upb_oneof_iter it; + + /* Check various conditions that would prevent this oneof from being added. */ if (upb_oneofdef_containingtype(o)) { upb_status_seterrmsg(s, "oneofdef already belongs to a message"); return false; @@ -1471,9 +1412,8 @@ bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor, return false; } - // Check that all of the oneof's fields do not conflict with names or numbers - // of fields already in the message. - upb_oneof_iter it; + /* Check that all of the oneof's fields do not conflict with names or numbers + * of fields already in the message. */ for (upb_oneof_begin(&it, o); !upb_oneof_done(&it); upb_oneof_next(&it)) { const upb_fielddef *f = upb_oneof_iter_field(&it); if (!check_field_add(m, f, s)) { @@ -1481,15 +1421,15 @@ bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor, } } - // Everything checks out -- commit now. + /* Everything checks out -- commit now. */ - // Add oneof itself first. + /* Add oneof itself first. */ o->parent = m; upb_strtable_insert(&m->ntoo, upb_oneofdef_name(o), upb_value_ptr(o)); upb_ref2(o, m); upb_ref2(m, o); - // Add each field of the oneof directly to the msgdef. + /* Add each field of the oneof directly to the msgdef. */ for (upb_oneof_begin(&it, o); !upb_oneof_done(&it); upb_oneof_next(&it)) { upb_fielddef *f = upb_oneof_iter_field(&it); add_field(m, f, NULL); @@ -1581,10 +1521,10 @@ static void visitoneof(const upb_refcounted *r, upb_refcounted_visit *visit, upb_oneof_iter i; for (upb_oneof_begin(&i, o); !upb_oneof_done(&i); upb_oneof_next(&i)) { const upb_fielddef *f = upb_oneof_iter_field(&i); - visit(r, UPB_UPCAST2(f), closure); + visit(r, upb_fielddef_upcast2(f), closure); } if (o->parent) { - visit(r, UPB_UPCAST2(o->parent), closure); + visit(r, upb_msgdef_upcast2(o->parent), closure); } } @@ -1592,7 +1532,7 @@ static void freeoneof(upb_refcounted *r) { upb_oneofdef *o = (upb_oneofdef*)r; upb_strtable_uninit(&o->ntof); upb_inttable_uninit(&o->itof); - upb_def_uninit(UPB_UPCAST(o)); + upb_def_uninit(upb_oneofdef_upcast_mutable(o)); free(o); } @@ -1601,7 +1541,9 @@ upb_oneofdef *upb_oneofdef_new(const void *owner) { upb_oneofdef *o = malloc(sizeof(*o)); o->parent = NULL; if (!o) return NULL; - if (!upb_def_init(UPB_UPCAST(o), UPB_DEF_ONEOF, &vtbl, owner)) goto err2; + if (!upb_def_init(upb_oneofdef_upcast_mutable(o), UPB_DEF_ONEOF, &vtbl, + owner)) + goto err2; if (!upb_inttable_init(&o->itof, UPB_CTYPE_PTR)) goto err2; if (!upb_strtable_init(&o->ntof, UPB_CTYPE_PTR)) goto err1; return o; @@ -1614,12 +1556,13 @@ err2: } upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner) { + bool ok; + upb_oneof_iter i; upb_oneofdef *newo = upb_oneofdef_new(owner); if (!newo) return NULL; - bool ok = upb_def_setfullname(UPB_UPCAST(newo), - upb_def_fullname(UPB_UPCAST(o)), NULL); + ok = upb_def_setfullname(upb_oneofdef_upcast_mutable(newo), + upb_def_fullname(upb_oneofdef_upcast(o)), NULL); UPB_ASSERT_VAR(ok, ok); - upb_oneof_iter i; for (upb_oneof_begin(&i, o); !upb_oneof_done(&i); upb_oneof_next(&i)) { upb_fielddef *f = upb_fielddef_dup(upb_oneof_iter_field(&i), &f); if (!f || !upb_oneofdef_addfield(newo, f, &f, NULL)) { @@ -1630,29 +1573,8 @@ upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner) { return newo; } -bool upb_oneofdef_isfrozen(const upb_oneofdef *o) { - return upb_def_isfrozen(UPB_UPCAST(o)); -} - -void upb_oneofdef_ref(const upb_oneofdef *o, const void *owner) { - upb_def_ref(UPB_UPCAST(o), owner); -} - -void upb_oneofdef_unref(const upb_oneofdef *o, const void *owner) { - upb_def_unref(UPB_UPCAST(o), owner); -} - -void upb_oneofdef_donateref(const upb_oneofdef *o, const void *from, - const void *to) { - upb_def_donateref(UPB_UPCAST(o), from, to); -} - -void upb_oneofdef_checkref(const upb_oneofdef *o, const void *owner) { - upb_def_checkref(UPB_UPCAST(o), owner); -} - const char *upb_oneofdef_name(const upb_oneofdef *o) { - return upb_def_fullname(UPB_UPCAST(o)); + return upb_def_fullname(upb_oneofdef_upcast(o)); } bool upb_oneofdef_setname(upb_oneofdef *o, const char *fullname, @@ -1661,7 +1583,7 @@ bool upb_oneofdef_setname(upb_oneofdef *o, const char *fullname, upb_status_seterrmsg(s, "oneof already added to a message"); return false; } - return upb_def_setfullname(UPB_UPCAST(o), fullname, s); + return upb_def_setfullname(upb_oneofdef_upcast_mutable(o), fullname, s); } const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) { @@ -1678,20 +1600,20 @@ bool upb_oneofdef_addfield(upb_oneofdef *o, upb_fielddef *f, assert(!upb_oneofdef_isfrozen(o)); assert(!o->parent || !upb_msgdef_isfrozen(o->parent)); - // This method is idempotent. Check if |f| is already part of this oneofdef - // and return immediately if so. + /* This method is idempotent. Check if |f| is already part of this oneofdef + * and return immediately if so. */ if (upb_fielddef_containingoneof(f) == o) { return true; } - // The field must have an OPTIONAL label. + /* The field must have an OPTIONAL label. */ if (upb_fielddef_label(f) != UPB_LABEL_OPTIONAL) { upb_status_seterrmsg(s, "fields in oneof must have OPTIONAL label"); return false; } - // Check that no field with this name or number exists already in the oneof. - // Also check that the field is not already part of a oneof. + /* Check that no field with this name or number exists already in the oneof. + * Also check that the field is not already part of a oneof. */ if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) { upb_status_seterrmsg(s, "field name or number were not set"); return false; @@ -1704,21 +1626,21 @@ bool upb_oneofdef_addfield(upb_oneofdef *o, upb_fielddef *f, return false; } - // We allow adding a field to the oneof either if the field is not part of a - // msgdef, or if it is and we are also part of the same msgdef. + /* We allow adding a field to the oneof either if the field is not part of a + * msgdef, or if it is and we are also part of the same msgdef. */ if (o->parent == NULL) { - // If we're not in a msgdef, the field cannot be either. Otherwise we would - // need to magically add this oneof to a msgdef to remain consistent, which - // is surprising behavior. + /* If we're not in a msgdef, the field cannot be either. Otherwise we would + * need to magically add this oneof to a msgdef to remain consistent, which + * is surprising behavior. */ if (upb_fielddef_containingtype(f) != NULL) { upb_status_seterrmsg(s, "fielddef already belongs to a message, but " "oneof does not"); return false; } } else { - // If we're in a msgdef, the user can add fields that either aren't in any - // msgdef (in which case they're added to our msgdef) or already a part of - // our msgdef. + /* If we're in a msgdef, the user can add fields that either aren't in any + * msgdef (in which case they're added to our msgdef) or already a part of + * our msgdef. */ if (upb_fielddef_containingtype(f) != NULL && upb_fielddef_containingtype(f) != o->parent) { upb_status_seterrmsg(s, "fielddef belongs to a different message " @@ -1727,8 +1649,8 @@ bool upb_oneofdef_addfield(upb_oneofdef *o, upb_fielddef *f, } } - // Commit phase. First add the field to our parent msgdef, if any, because - // that may fail; then add the field to our own tables. + /* Commit phase. First add the field to our parent msgdef, if any, because + * that may fail; then add the field to our own tables. */ if (o->parent != NULL && upb_fielddef_containingtype(f) == NULL) { if (!upb_msgdef_addfield((upb_msgdef*)o->parent, f, NULL, s)) { @@ -1801,18 +1723,17 @@ static void *seeded_alloc(void *ud, void *ptr, size_t oldsize, size_t size); /* Default allocator **********************************************************/ -// Just use realloc, keeping all allocated blocks in a linked list to destroy at -// the end. +/* Just use realloc, keeping all allocated blocks in a linked list to destroy at + * the end. */ typedef struct mem_block { - // List is doubly-linked, because in cases where realloc() moves an existing - // block, we need to be able to remove the old pointer from the list - // efficiently. + /* List is doubly-linked, because in cases where realloc() moves an existing + * block, we need to be able to remove the old pointer from the list + * efficiently. */ struct mem_block *prev, *next; #ifndef NDEBUG - size_t size; // Doesn't include mem_block structure. + size_t size; /* Doesn't include mem_block structure. */ #endif - char data[]; } mem_block; typedef struct { @@ -1820,10 +1741,12 @@ typedef struct { } default_alloc_ud; static void *default_alloc(void *_ud, void *ptr, size_t oldsize, size_t size) { - UPB_UNUSED(oldsize); default_alloc_ud *ud = _ud; + mem_block *from, *block; + void *ret; + UPB_UNUSED(oldsize); - mem_block *from = ptr ? (void*)((char*)ptr - sizeof(mem_block)) : NULL; + from = ptr ? (void*)((char*)ptr - sizeof(mem_block)) : NULL; #ifndef NDEBUG if (from) { @@ -1831,8 +1754,11 @@ static void *default_alloc(void *_ud, void *ptr, size_t oldsize, size_t size) { } #endif - mem_block *block = realloc(from, size + sizeof(mem_block)); + /* TODO(haberman): we probably need to provide even better alignment here, + * like 16-byte alignment of the returned data pointer. */ + block = realloc(from, size + sizeof(mem_block)); if (!block) return NULL; + ret = (char*)block + sizeof(*block); #ifndef NDEBUG block->size = size; @@ -1840,20 +1766,21 @@ static void *default_alloc(void *_ud, void *ptr, size_t oldsize, size_t size) { if (from) { if (block != from) { - // The block was moved, so pointers in next and prev blocks must be - // updated to its new location. + /* The block was moved, so pointers in next and prev blocks must be + * updated to its new location. */ if (block->next) block->next->prev = block; if (block->prev) block->prev->next = block; + if (ud->head == from) ud->head = block; } } else { - // Insert at head of linked list. + /* Insert at head of linked list. */ block->prev = NULL; block->next = ud->head; if (block->next) block->next->prev = block; ud->head = block; } - return &block->data; + return ret; } static void default_alloc_cleanup(void *_ud) { @@ -1872,7 +1799,7 @@ static void default_alloc_cleanup(void *_ud) { static bool default_err(void *ud, const upb_status *status) { UPB_UNUSED(ud); - fprintf(stderr, "upb error: %s\n", upb_status_errmsg(status)); + UPB_UNUSED(status); return false; } @@ -1886,14 +1813,14 @@ static bool write_err_to(void *ud, const upb_status *status) { /* upb_env ********************************************************************/ void upb_env_init(upb_env *e) { + default_alloc_ud *ud = (default_alloc_ud*)&e->default_alloc_ud; e->ok_ = true; e->bytes_allocated = 0; e->cleanup_head = NULL; - default_alloc_ud *ud = (default_alloc_ud*)&e->default_alloc_ud; ud->head = NULL; - // Set default functions. + /* Set default functions. */ upb_env_setallocfunc(e, default_alloc, ud); upb_env_seterrorfunc(e, default_err, NULL); } @@ -1906,8 +1833,8 @@ void upb_env_uninit(upb_env *e) { ent = ent->next; } - // Must do this after running cleanup functions, because this will delete - // the memory we store our cleanup entries in! + /* Must do this after running cleanup functions, because this will delete + the memory we store our cleanup entries in! */ if (e->alloc == default_alloc) { default_alloc_cleanup(e->alloc_ud); } @@ -1954,8 +1881,8 @@ bool upb_env_addcleanup(upb_env *e, upb_cleanup_func *func, void *ud) { void *upb_env_malloc(upb_env *e, size_t size) { e->bytes_allocated += size; if (e->alloc == seeded_alloc) { - // This is equivalent to the next branch, but allows inlining for a - // measurable perf benefit. + /* This is equivalent to the next branch, but allows inlining for a + * measurable perf benefit. */ return seeded_alloc(e->alloc_ud, NULL, 0, size); } else { return e->alloc(e->alloc_ud, NULL, 0, size); @@ -1963,12 +1890,13 @@ void *upb_env_malloc(upb_env *e, size_t size) { } void *upb_env_realloc(upb_env *e, void *ptr, size_t oldsize, size_t size) { + char *ret; assert(oldsize <= size); - char *ret = e->alloc(e->alloc_ud, ptr, oldsize, size); + ret = e->alloc(e->alloc_ud, ptr, oldsize, size); #ifndef NDEBUG - // Overwrite non-preserved memory to ensure callers are passing the oldsize - // that they truly require. + /* Overwrite non-preserved memory to ensure callers are passing the oldsize + * that they truly require. */ memset(ret + oldsize, 0xff, size - oldsize); #endif @@ -1982,7 +1910,7 @@ size_t upb_env_bytesallocated(const upb_env *e) { /* upb_seededalloc ************************************************************/ -// Be conservative and choose 16 in case anyone is using SSE. +/* Be conservative and choose 16 in case anyone is using SSE. */ static const size_t maxalign = 16; static size_t align_up(size_t size) { @@ -1991,26 +1919,29 @@ static size_t align_up(size_t size) { UPB_FORCEINLINE static void *seeded_alloc(void *ud, void *ptr, size_t oldsize, size_t size) { - UPB_UNUSED(ptr); - upb_seededalloc *a = ud; + size = align_up(size); assert(a->mem_limit >= a->mem_ptr); if (oldsize == 0 && size <= (size_t)(a->mem_limit - a->mem_ptr)) { - // Fast path: we can satisfy from the initial allocation. + /* Fast path: we can satisfy from the initial allocation. */ void *ret = a->mem_ptr; a->mem_ptr += size; return ret; } else { - // Slow path: fallback to other allocator. - a->need_cleanup = true; - // Is `ptr` part of the user-provided initial block? Don't pass it to the - // default allocator if so; otherwise, it may try to realloc() the block. char *chptr = ptr; + /* Slow path: fallback to other allocator. */ + a->need_cleanup = true; + /* Is `ptr` part of the user-provided initial block? Don't pass it to the + * default allocator if so; otherwise, it may try to realloc() the block. */ if (chptr >= a->mem_base && chptr < a->mem_limit) { - return a->alloc(a->alloc_ud, NULL, 0, size); + void *ret; + assert(chptr + oldsize <= a->mem_limit); + ret = a->alloc(a->alloc_ud, NULL, 0, size); + if (ret) memcpy(ret, ptr, oldsize); + return ret; } else { return a->alloc(a->alloc_ud, ptr, oldsize, size); } @@ -2018,13 +1949,13 @@ UPB_FORCEINLINE static void *seeded_alloc(void *ud, void *ptr, size_t oldsize, } void upb_seededalloc_init(upb_seededalloc *a, void *mem, size_t len) { + default_alloc_ud *ud = (default_alloc_ud*)&a->default_alloc_ud; a->mem_base = mem; a->mem_ptr = mem; a->mem_limit = (char*)mem + len; a->need_cleanup = false; a->returned_allocfunc = false; - default_alloc_ud *ud = (default_alloc_ud*)&a->default_alloc_ud; ud->head = NULL; upb_seededalloc_setfallbackalloc(a, default_alloc, ud); @@ -2063,8 +1994,9 @@ upb_alloc_func *upb_seededalloc_getallocfunc(upb_seededalloc *a) { #include <string.h> -// Defined for the sole purpose of having a unique pointer value for -// UPB_NO_CLOSURE. + +/* Defined for the sole purpose of having a unique pointer value for + * UPB_NO_CLOSURE. */ char _upb_noclosure; static void freehandlers(upb_refcounted *r) { @@ -2093,42 +2025,45 @@ static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit, !upb_msg_field_done(&i); upb_msg_field_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); + const upb_handlers *sub; if (!upb_fielddef_issubmsg(f)) continue; - const upb_handlers *sub = upb_handlers_getsubhandlers(h, f); - if (sub) visit(r, UPB_UPCAST(sub), closure); + sub = upb_handlers_getsubhandlers(h, f); + if (sub) visit(r, upb_handlers_upcast(sub), closure); } } static const struct upb_refcounted_vtbl vtbl = {visithandlers, freehandlers}; typedef struct { - upb_inttable tab; // maps upb_msgdef* -> upb_handlers*. + upb_inttable tab; /* maps upb_msgdef* -> upb_handlers*. */ upb_handlers_callback *callback; const void *closure; } dfs_state; -// TODO(haberman): discard upb_handlers* objects that do not actually have any -// handlers set and cannot reach any upb_handlers* object that does. This is -// slightly tricky to do correctly. +/* TODO(haberman): discard upb_handlers* objects that do not actually have any + * handlers set and cannot reach any upb_handlers* object that does. This is + * slightly tricky to do correctly. */ static upb_handlers *newformsg(const upb_msgdef *m, const void *owner, dfs_state *s) { + upb_msg_field_iter i; upb_handlers *h = upb_handlers_new(m, owner); if (!h) return NULL; if (!upb_inttable_insertptr(&s->tab, m, upb_value_ptr(h))) goto oom; s->callback(s->closure, h); - // For each submessage field, get or create a handlers object and set it as - // the subhandlers. - upb_msg_field_iter i; + /* For each submessage field, get or create a handlers object and set it as + * the subhandlers. */ for(upb_msg_field_begin(&i, m); !upb_msg_field_done(&i); upb_msg_field_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); + const upb_msgdef *subdef; + upb_value subm_ent; + if (!upb_fielddef_issubmsg(f)) continue; - const upb_msgdef *subdef = upb_downcast_msgdef(upb_fielddef_subdef(f)); - upb_value subm_ent; + subdef = upb_downcast_msgdef(upb_fielddef_subdef(f)); if (upb_inttable_lookupptr(&s->tab, subdef, &subm_ent)) { upb_handlers_setsubhandlers(h, f, upb_value_getptr(subm_ent)); } else { @@ -2145,11 +2080,11 @@ oom: return NULL; } -// Given a selector for a STARTSUBMSG handler, resolves to a pointer to the -// subhandlers for this submessage field. +/* Given a selector for a STARTSUBMSG handler, resolves to a pointer to the + * subhandlers for this submessage field. */ #define SUBH(h, selector) (h->sub[selector]) -// The selector for a submessage field is the field index. +/* The selector for a submessage field is the field index. */ #define SUBH_F(h, f) SUBH(h, f->index_) static int32_t trygetsel(upb_handlers *h, const upb_fielddef *f, @@ -2187,6 +2122,10 @@ static const void **returntype(upb_handlers *h, const upb_fielddef *f, static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f, upb_handlertype_t type, upb_func *func, upb_handlerattr *attr) { + upb_handlerattr set_attr = UPB_HANDLERATTR_INITIALIZER; + const void *closure_type; + const void **context_closure_type; + assert(!upb_handlers_isfrozen(h)); if (sel < 0) { @@ -2201,15 +2140,13 @@ static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f, return false; } - upb_handlerattr set_attr = UPB_HANDLERATTR_INITIALIZER; if (attr) { set_attr = *attr; } - // Check that the given closure type matches the closure type that has been - // established for this context (if any). - const void *closure_type = upb_handlerattr_closuretype(&set_attr); - const void **context_closure_type; + /* Check that the given closure type matches the closure type that has been + * established for this context (if any). */ + closure_type = upb_handlerattr_closuretype(&set_attr); if (type == UPB_HANDLER_STRING) { context_closure_type = returntype(h, f, UPB_HANDLER_STARTSTR); @@ -2223,7 +2160,7 @@ static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f, if (closure_type && *context_closure_type && closure_type != *context_closure_type) { - // TODO(haberman): better message for debugging. + /* TODO(haberman): better message for debugging. */ if (f) { upb_status_seterrf(&h->status_, "closure type does not match for field %s", @@ -2238,8 +2175,8 @@ static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f, if (closure_type) *context_closure_type = closure_type; - // If this is a STARTSEQ or STARTSTR handler, check that the returned pointer - // matches any pre-existing expectations about what type is expected. + /* If this is a STARTSEQ or STARTSTR handler, check that the returned pointer + * matches any pre-existing expectations about what type is expected. */ if (type == UPB_HANDLER_STARTSEQ || type == UPB_HANDLER_STARTSTR) { const void *return_type = upb_handlerattr_returnclosuretype(&set_attr); const void *table_return_type = @@ -2258,17 +2195,20 @@ static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f, return true; } -// Returns the effective closure type for this handler (which will propagate -// from outer frames if this frame has no START* handler). Not implemented for -// UPB_HANDLER_STRING at the moment since this is not needed. Returns NULL is -// the effective closure type is unspecified (either no handler was registered -// to specify it or the handler that was registered did not specify the closure -// type). +/* Returns the effective closure type for this handler (which will propagate + * from outer frames if this frame has no START* handler). Not implemented for + * UPB_HANDLER_STRING at the moment since this is not needed. Returns NULL is + * the effective closure type is unspecified (either no handler was registered + * to specify it or the handler that was registered did not specify the closure + * type). */ const void *effective_closure_type(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type) { - assert(type != UPB_HANDLER_STRING); - const void *ret = h->top_closure_type; + const void *ret; upb_selector_t sel; + + assert(type != UPB_HANDLER_STRING); + ret = h->top_closure_type; + if (upb_fielddef_isseq(f) && type != UPB_HANDLER_STARTSEQ && type != UPB_HANDLER_ENDSEQ && @@ -2281,26 +2221,30 @@ const void *effective_closure_type(upb_handlers *h, const upb_fielddef *f, ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr); } - // The effective type of the submessage; not used yet. - // if (type == SUBMESSAGE && - // h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)].func) { - // ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr); - // } + /* The effective type of the submessage; not used yet. + * if (type == SUBMESSAGE && + * h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)].func) { + * ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr); + * } */ return ret; } -// Checks whether the START* handler specified by f & type is missing even -// though it is required to convert the established type of an outer frame -// ("closure_type") into the established type of an inner frame (represented in -// the return closure type of this handler's attr. +/* Checks whether the START* handler specified by f & type is missing even + * though it is required to convert the established type of an outer frame + * ("closure_type") into the established type of an inner frame (represented in + * the return closure type of this handler's attr. */ bool checkstart(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type, upb_status *status) { + const void *closure_type; + const upb_handlerattr *attr; + const void *return_closure_type; + upb_selector_t sel = handlers_getsel(h, f, type); if (h->table[sel].func) return true; - const void *closure_type = effective_closure_type(h, f, type); - const upb_handlerattr *attr = &h->table[sel].attr; - const void *return_closure_type = upb_handlerattr_returnclosuretype(attr); + closure_type = effective_closure_type(h, f, type); + attr = &h->table[sel].attr; + return_closure_type = upb_handlerattr_returnclosuretype(attr); if (closure_type && return_closure_type && closure_type != return_closure_type) { upb_status_seterrf(status, @@ -2313,32 +2257,14 @@ bool checkstart(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type, /* Public interface ***********************************************************/ -bool upb_handlers_isfrozen(const upb_handlers *h) { - return upb_refcounted_isfrozen(UPB_UPCAST(h)); -} - -void upb_handlers_ref(const upb_handlers *h, const void *owner) { - upb_refcounted_ref(UPB_UPCAST(h), owner); -} - -void upb_handlers_unref(const upb_handlers *h, const void *owner) { - upb_refcounted_unref(UPB_UPCAST(h), owner); -} - -void upb_handlers_donateref( - const upb_handlers *h, const void *from, const void *to) { - upb_refcounted_donateref(UPB_UPCAST(h), from, to); -} - -void upb_handlers_checkref(const upb_handlers *h, const void *owner) { - upb_refcounted_checkref(UPB_UPCAST(h), owner); -} - upb_handlers *upb_handlers_new(const upb_msgdef *md, const void *owner) { + int extra; + upb_handlers *h; + assert(upb_msgdef_isfrozen(md)); - int extra = sizeof(upb_handlers_tabent) * (md->selector_count - 1); - upb_handlers *h = calloc(sizeof(*h) + extra, 1); + extra = sizeof(upb_handlers_tabent) * (md->selector_count - 1); + h = calloc(sizeof(*h) + extra, 1); if (!h) return NULL; h->msg = md; @@ -2346,14 +2272,15 @@ upb_handlers *upb_handlers_new(const upb_msgdef *md, const void *owner) { upb_status_clear(&h->status_); h->sub = calloc(md->submsg_field_count, sizeof(*h->sub)); if (!h->sub) goto oom; - if (!upb_refcounted_init(UPB_UPCAST(h), &vtbl, owner)) goto oom; + if (!upb_refcounted_init(upb_handlers_upcast_mutable(h), &vtbl, owner)) + goto oom; if (!upb_inttable_init(&h->cleanup_, UPB_CTYPE_FPTR)) goto oom; - // calloc() above initialized all handlers to NULL. + /* calloc() above initialized all handlers to NULL. */ return h; oom: - freehandlers(UPB_UPCAST(h)); + freehandlers(upb_handlers_upcast_mutable(h)); return NULL; } @@ -2362,17 +2289,21 @@ const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m, upb_handlers_callback *callback, const void *closure) { dfs_state state; + upb_handlers *ret; + bool ok; + upb_refcounted *r; + state.callback = callback; state.closure = closure; if (!upb_inttable_init(&state.tab, UPB_CTYPE_PTR)) return NULL; - upb_handlers *ret = newformsg(m, owner, &state); + ret = newformsg(m, owner, &state); upb_inttable_uninit(&state.tab); if (!ret) return NULL; - upb_refcounted *r = UPB_UPCAST(ret); - bool ok = upb_refcounted_freeze(&r, 1, NULL, UPB_MAX_HANDLER_DEPTH); + r = upb_handlers_upcast_mutable(ret); + ok = upb_refcounted_freeze(&r, 1, NULL, UPB_MAX_HANDLER_DEPTH); UPB_ASSERT_VAR(ok, ok); return ret; @@ -2395,20 +2326,20 @@ void upb_handlers_clearerr(upb_handlers *h) { return doset(h, sel, f, handlertype, (upb_func*)func, attr); \ } -SETTER(int32, upb_int32_handlerfunc*, UPB_HANDLER_INT32); -SETTER(int64, upb_int64_handlerfunc*, UPB_HANDLER_INT64); -SETTER(uint32, upb_uint32_handlerfunc*, UPB_HANDLER_UINT32); -SETTER(uint64, upb_uint64_handlerfunc*, UPB_HANDLER_UINT64); -SETTER(float, upb_float_handlerfunc*, UPB_HANDLER_FLOAT); -SETTER(double, upb_double_handlerfunc*, UPB_HANDLER_DOUBLE); -SETTER(bool, upb_bool_handlerfunc*, UPB_HANDLER_BOOL); -SETTER(startstr, upb_startstr_handlerfunc*, UPB_HANDLER_STARTSTR); -SETTER(string, upb_string_handlerfunc*, UPB_HANDLER_STRING); -SETTER(endstr, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSTR); -SETTER(startseq, upb_startfield_handlerfunc*, UPB_HANDLER_STARTSEQ); -SETTER(startsubmsg, upb_startfield_handlerfunc*, UPB_HANDLER_STARTSUBMSG); -SETTER(endsubmsg, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSUBMSG); -SETTER(endseq, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSEQ); +SETTER(int32, upb_int32_handlerfunc*, UPB_HANDLER_INT32) +SETTER(int64, upb_int64_handlerfunc*, UPB_HANDLER_INT64) +SETTER(uint32, upb_uint32_handlerfunc*, UPB_HANDLER_UINT32) +SETTER(uint64, upb_uint64_handlerfunc*, UPB_HANDLER_UINT64) +SETTER(float, upb_float_handlerfunc*, UPB_HANDLER_FLOAT) +SETTER(double, upb_double_handlerfunc*, UPB_HANDLER_DOUBLE) +SETTER(bool, upb_bool_handlerfunc*, UPB_HANDLER_BOOL) +SETTER(startstr, upb_startstr_handlerfunc*, UPB_HANDLER_STARTSTR) +SETTER(string, upb_string_handlerfunc*, UPB_HANDLER_STRING) +SETTER(endstr, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSTR) +SETTER(startseq, upb_startfield_handlerfunc*, UPB_HANDLER_STARTSEQ) +SETTER(startsubmsg, upb_startfield_handlerfunc*, UPB_HANDLER_STARTSUBMSG) +SETTER(endsubmsg, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSUBMSG) +SETTER(endseq, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSEQ) #undef SETTER @@ -2430,8 +2361,8 @@ bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f, assert(sub); assert(!upb_handlers_isfrozen(h)); assert(upb_fielddef_issubmsg(f)); - if (SUBH_F(h, f)) return false; // Can't reset. - if (UPB_UPCAST(upb_handlers_msgdef(sub)) != upb_fielddef_subdef(f)) { + if (SUBH_F(h, f)) return false; /* Can't reset. */ + if (upb_msgdef_upcast(upb_handlers_msgdef(sub)) != upb_fielddef_subdef(f)) { return false; } SUBH_F(h, f) = sub; @@ -2455,17 +2386,18 @@ bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t sel, const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h, upb_selector_t sel) { - // STARTSUBMSG selector in sel is the field's selector base. + /* STARTSUBMSG selector in sel is the field's selector base. */ return SUBH(h, sel - UPB_STATIC_SELECTOR_COUNT); } const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; } bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *func) { + bool ok; if (upb_inttable_lookupptr(&h->cleanup_, p, NULL)) { return false; } - bool ok = upb_inttable_insertptr(&h->cleanup_, p, upb_value_fptr(func)); + ok = upb_inttable_insertptr(&h->cleanup_, p, upb_value_fptr(func)); UPB_ASSERT_VAR(ok, ok); return true; } @@ -2474,8 +2406,10 @@ bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *func) { /* "Static" methods ***********************************************************/ bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) { - // TODO: verify we have a transitive closure. - for (int i = 0; i < n; i++) { + /* TODO: verify we have a transitive closure. */ + int i; + for (i = 0; i < n; i++) { + upb_msg_field_iter j; upb_handlers *h = handlers[i]; if (!upb_ok(&h->status_)) { @@ -2485,9 +2419,8 @@ bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) { return false; } - // Check that there are no closure mismatches due to missing Start* handlers - // or subhandlers with different type-level types. - upb_msg_field_iter j; + /* Check that there are no closure mismatches due to missing Start* handlers + * or subhandlers with different type-level types. */ for(upb_msg_field_begin(&j, h->msg); !upb_msg_field_done(&j); upb_msg_field_next(&j)) { @@ -2521,29 +2454,29 @@ bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) { } if (hashandler && !upb_handlers_getsubhandlers(h, f)) { - // For now we add an empty subhandlers in this case. It makes the - // decoder code generator simpler, because it only has to handle two - // cases (submessage has handlers or not) as opposed to three - // (submessage has handlers in enclosing message but no subhandlers). - // - // This makes parsing less efficient in the case that we want to - // notice a submessage but skip its contents (like if we're testing - // for submessage presence or counting the number of repeated - // submessages). In this case we will end up parsing the submessage - // field by field and throwing away the results for each, instead of - // skipping the whole delimited thing at once. If this is an issue we - // can revisit it, but do remember that this only arises when you have - // handlers (startseq/startsubmsg/endsubmsg/endseq) set for the - // submessage but no subhandlers. The uses cases for this are - // limited. + /* For now we add an empty subhandlers in this case. It makes the + * decoder code generator simpler, because it only has to handle two + * cases (submessage has handlers or not) as opposed to three + * (submessage has handlers in enclosing message but no subhandlers). + * + * This makes parsing less efficient in the case that we want to + * notice a submessage but skip its contents (like if we're testing + * for submessage presence or counting the number of repeated + * submessages). In this case we will end up parsing the submessage + * field by field and throwing away the results for each, instead of + * skipping the whole delimited thing at once. If this is an issue we + * can revisit it, but do remember that this only arises when you have + * handlers (startseq/startsubmsg/endsubmsg/endseq) set for the + * submessage but no subhandlers. The uses cases for this are + * limited. */ upb_handlers *sub = upb_handlers_new(upb_fielddef_msgsubdef(f), &sub); upb_handlers_setsubhandlers(h, f, sub); upb_handlers_unref(sub, &sub); } - // TODO(haberman): check type of submessage. - // This is slightly tricky; also consider whether we should check that - // they match at setsubhandlers time. + /* TODO(haberman): check type of submessage. + * This is slightly tricky; also consider whether we should check that + * they match at setsubhandlers time. */ } } } @@ -2566,7 +2499,7 @@ upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f) { case UPB_TYPE_FLOAT: return UPB_HANDLER_FLOAT; case UPB_TYPE_DOUBLE: return UPB_HANDLER_DOUBLE; case UPB_TYPE_BOOL: return UPB_HANDLER_BOOL; - default: assert(false); return -1; // Invalid input. + default: assert(false); return -1; /* Invalid input. */ } } @@ -2618,10 +2551,10 @@ bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type, break; case UPB_HANDLER_STARTSUBMSG: if (!upb_fielddef_issubmsg(f)) return false; - // Selectors for STARTSUBMSG are at the beginning of the table so that the - // selector can also be used as an index into the "sub" array of - // subhandlers. The indexes for the two into these two tables are the - // same, except that in the handler table the static selectors come first. + /* Selectors for STARTSUBMSG are at the beginning of the table so that the + * selector can also be used as an index into the "sub" array of + * subhandlers. The indexes for the two into these two tables are the + * same, except that in the handler table the static selectors come first. */ *s = f->index_ + UPB_STATIC_SELECTOR_COUNT; break; case UPB_HANDLER_ENDSUBMSG: @@ -2639,13 +2572,13 @@ uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) { uint32_t upb_handlers_selectorcount(const upb_fielddef *f) { uint32_t ret = 1; - if (upb_fielddef_isseq(f)) ret += 2; // STARTSEQ/ENDSEQ - if (upb_fielddef_isstring(f)) ret += 2; // [STRING]/STARTSTR/ENDSTR + if (upb_fielddef_isseq(f)) ret += 2; /* STARTSEQ/ENDSEQ */ + if (upb_fielddef_isstring(f)) ret += 2; /* [STRING]/STARTSTR/ENDSTR */ if (upb_fielddef_issubmsg(f)) { - // ENDSUBMSG (STARTSUBMSG is at table beginning) + /* ENDSUBMSG (STARTSUBMSG is at table beginning) */ ret += 0; if (upb_fielddef_lazy(f)) { - // STARTSTR/ENDSTR/STRING (for lazy) + /* STARTSTR/ENDSTR/STRING (for lazy) */ ret += 3; } } @@ -2709,7 +2642,7 @@ void upb_byteshandler_init(upb_byteshandler* h) { memset(h, 0, sizeof(*h)); } -// For when we support handlerfree callbacks. +/* For when we support handlerfree callbacks. */ void upb_byteshandler_uninit(upb_byteshandler* h) { UPB_UNUSED(h); } @@ -2765,17 +2698,17 @@ const void *UPB_UNTRACKED_REF = &untracked_val; /* arch-specific atomic primitives *******************************************/ -#ifdef UPB_THREAD_UNSAFE ////////////////////////////////////////////////////// +#ifdef UPB_THREAD_UNSAFE /*---------------------------------------------------*/ static void atomic_inc(uint32_t *a) { (*a)++; } static bool atomic_dec(uint32_t *a) { return --(*a) == 0; } -#elif defined(__GNUC__) || defined(__clang__) ////////////////////////////////// +#elif defined(__GNUC__) || defined(__clang__) /*------------------------------*/ static void atomic_inc(uint32_t *a) { __sync_fetch_and_add(a, 1); } static bool atomic_dec(uint32_t *a) { return __sync_sub_and_fetch(a, 1) == 0; } -#elif defined(WIN32) /////////////////////////////////////////////////////////// +#elif defined(WIN32) /*-------------------------------------------------------*/ #include <Windows.h> @@ -2789,13 +2722,13 @@ static bool atomic_dec(upb_atomic_t *a) { Implement them or compile with UPB_THREAD_UNSAFE. #endif -// All static objects point to this refcount. -// It is special-cased in ref/unref below. +/* All static objects point to this refcount. + * It is special-cased in ref/unref below. */ uint32_t static_refcount = -1; -// We can avoid atomic ops for statically-declared objects. -// This is a minor optimization but nice since we can avoid degrading under -// contention in this case. +/* We can avoid atomic ops for statically-declared objects. + * This is a minor optimization but nice since we can avoid degrading under + * contention in this case. */ static void refgroup(uint32_t *group) { if (group != &static_refcount) @@ -2822,21 +2755,21 @@ static void upb_unlock() {} #else -// User must define functions that lock/unlock a global mutex and link this -// file against them. +/* User must define functions that lock/unlock a global mutex and link this + * file against them. */ void upb_lock(); void upb_unlock(); #endif -// UPB_DEBUG_REFS mode counts on being able to malloc() memory in some -// code-paths that can normally never fail, like upb_refcounted_ref(). Since -// we have no way to propagage out-of-memory errors back to the user, and since -// these errors can only occur in UPB_DEBUG_REFS mode, we immediately fail. +/* UPB_DEBUG_REFS mode counts on being able to malloc() memory in some + * code-paths that can normally never fail, like upb_refcounted_ref(). Since + * we have no way to propagage out-of-memory errors back to the user, and since + * these errors can only occur in UPB_DEBUG_REFS mode, we immediately fail. */ #define CHECK_OOM(predicate) if (!(predicate)) { assert(predicate); exit(1); } typedef struct { - int count; // How many refs there are (duplicates only allowed for ref2). + int count; /* How many refs there are (duplicates only allowed for ref2). */ bool is_ref2; } trackedref; @@ -2849,18 +2782,19 @@ static trackedref *trackedref_new(bool is_ref2) { } static void track(const upb_refcounted *r, const void *owner, bool ref2) { + upb_value v; + assert(owner); if (owner == UPB_UNTRACKED_REF) return; upb_lock(); - upb_value v; if (upb_inttable_lookupptr(r->refs, owner, &v)) { trackedref *ref = upb_value_getptr(v); - // Since we allow multiple ref2's for the same to/from pair without - // allocating separate memory for each one, we lose the fine-grained - // tracking behavior we get with regular refs. Since ref2s only happen - // inside upb, we'll accept this limitation until/unless there is a really - // difficult upb-internal bug that can't be figured out without it. + /* Since we allow multiple ref2's for the same to/from pair without + * allocating separate memory for each one, we lose the fine-grained + * tracking behavior we get with regular refs. Since ref2s only happen + * inside upb, we'll accept this limitation until/unless there is a really + * difficult upb-internal bug that can't be figured out without it. */ assert(ref2); assert(ref->is_ref2); ref->count++; @@ -2869,8 +2803,8 @@ static void track(const upb_refcounted *r, const void *owner, bool ref2) { bool ok = upb_inttable_insertptr(r->refs, owner, upb_value_ptr(ref)); CHECK_OOM(ok); if (ref2) { - // We know this cast is safe when it is a ref2, because it's coming from - // another refcounted object. + /* We know this cast is safe when it is a ref2, because it's coming from + * another refcounted object. */ const upb_refcounted *from = owner; assert(!upb_inttable_lookupptr(from->ref2s, r, NULL)); ok = upb_inttable_insertptr(from->ref2s, r, upb_value_ptr(NULL)); @@ -2881,22 +2815,25 @@ static void track(const upb_refcounted *r, const void *owner, bool ref2) { } static void untrack(const upb_refcounted *r, const void *owner, bool ref2) { + upb_value v; + bool found; + trackedref *ref; + assert(owner); if (owner == UPB_UNTRACKED_REF) return; upb_lock(); - upb_value v; - bool found = upb_inttable_lookupptr(r->refs, owner, &v); - // This assert will fail if an owner attempts to release a ref it didn't have. + found = upb_inttable_lookupptr(r->refs, owner, &v); + /* This assert will fail if an owner attempts to release a ref it didn't have. */ UPB_ASSERT_VAR(found, found); - trackedref *ref = upb_value_getptr(v); + ref = upb_value_getptr(v); assert(ref->is_ref2 == ref2); if (--ref->count == 0) { free(ref); upb_inttable_removeptr(r->refs, owner, NULL); if (ref2) { - // We know this cast is safe when it is a ref2, because it's coming from - // another refcounted object. + /* We know this cast is safe when it is a ref2, because it's coming from + * another refcounted object. */ const upb_refcounted *from = owner; bool removed = upb_inttable_removeptr(from->ref2s, r, NULL); assert(removed); @@ -2906,32 +2843,41 @@ static void untrack(const upb_refcounted *r, const void *owner, bool ref2) { } static void checkref(const upb_refcounted *r, const void *owner, bool ref2) { - upb_lock(); upb_value v; - bool found = upb_inttable_lookupptr(r->refs, owner, &v); + bool found; + trackedref *ref; + + upb_lock(); + found = upb_inttable_lookupptr(r->refs, owner, &v); UPB_ASSERT_VAR(found, found); - trackedref *ref = upb_value_getptr(v); + ref = upb_value_getptr(v); assert(ref->is_ref2 == ref2); upb_unlock(); } -// Populates the given UPB_CTYPE_INT32 inttable with counts of ref2's that -// originate from the given owner. +/* Populates the given UPB_CTYPE_INT32 inttable with counts of ref2's that + * originate from the given owner. */ static void getref2s(const upb_refcounted *owner, upb_inttable *tab) { - upb_lock(); upb_inttable_iter i; + + upb_lock(); upb_inttable_begin(&i, owner->ref2s); for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { + upb_value v; + upb_value count; + trackedref *ref; + bool ok; + bool found; + upb_refcounted *to = (upb_refcounted*)upb_inttable_iter_key(&i); - // To get the count we need to look in the target's table. - upb_value v; - bool found = upb_inttable_lookupptr(to->refs, owner, &v); + /* To get the count we need to look in the target's table. */ + found = upb_inttable_lookupptr(to->refs, owner, &v); assert(found); - trackedref *ref = upb_value_getptr(v); - upb_value count = upb_value_int32(ref->count); + ref = upb_value_getptr(v); + count = upb_value_int32(ref->count); - bool ok = upb_inttable_insertptr(tab, to, count); + ok = upb_inttable_insertptr(tab, to, count); CHECK_OOM(ok); } upb_unlock(); @@ -2945,15 +2891,18 @@ typedef struct { static void visit_check(const upb_refcounted *obj, const upb_refcounted *subobj, void *closure) { check_state *s = closure; - assert(obj == s->obj); - assert(subobj); upb_inttable *ref2 = &s->ref2; upb_value v; - bool removed = upb_inttable_removeptr(ref2, subobj, &v); - // The following assertion will fail if the visit() function visits a subobj - // that it did not have a ref2 on, or visits the same subobj too many times. + bool removed; + int32_t newcount; + + assert(obj == s->obj); + assert(subobj); + removed = upb_inttable_removeptr(ref2, subobj, &v); + /* The following assertion will fail if the visit() function visits a subobj + * that it did not have a ref2 on, or visits the same subobj too many times. */ assert(removed); - int32_t newcount = upb_value_getint32(v) - 1; + newcount = upb_value_getint32(v) - 1; if (newcount > 0) { upb_inttable_insert(ref2, (uintptr_t)subobj, upb_value_int32(newcount)); } @@ -2961,19 +2910,21 @@ static void visit_check(const upb_refcounted *obj, const upb_refcounted *subobj, static void visit(const upb_refcounted *r, upb_refcounted_visit *v, void *closure) { - // In DEBUG_REFS mode we know what existing ref2 refs there are, so we know - // exactly the set of nodes that visit() should visit. So we verify visit()'s - // correctness here. + bool ok; + + /* In DEBUG_REFS mode we know what existing ref2 refs there are, so we know + * exactly the set of nodes that visit() should visit. So we verify visit()'s + * correctness here. */ check_state state; state.obj = r; - bool ok = upb_inttable_init(&state.ref2, UPB_CTYPE_INT32); + ok = upb_inttable_init(&state.ref2, UPB_CTYPE_INT32); CHECK_OOM(ok); getref2s(r, &state.ref2); - // This should visit any children in the ref2 table. + /* This should visit any children in the ref2 table. */ if (r->vtbl->visit) r->vtbl->visit(r, visit_check, &state); - // This assertion will fail if the visit() function missed any children. + /* This assertion will fail if the visit() function missed any children. */ assert(upb_inttable_count(&state.ref2) == 0); upb_inttable_uninit(&state.ref2); if (r->vtbl->visit) r->vtbl->visit(r, v, closure); @@ -3037,27 +2988,27 @@ static void visit(const upb_refcounted *r, upb_refcounted_visit *v, if (r->vtbl->visit) r->vtbl->visit(r, v, closure); } -#endif // UPB_DEBUG_REFS +#endif /* UPB_DEBUG_REFS */ /* freeze() *******************************************************************/ -// The freeze() operation is by far the most complicated part of this scheme. -// We compute strongly-connected components and then mutate the graph such that -// we preserve the invariants documented at the top of this file. And we must -// handle out-of-memory errors gracefully (without leaving the graph -// inconsistent), which adds to the fun. +/* The freeze() operation is by far the most complicated part of this scheme. + * We compute strongly-connected components and then mutate the graph such that + * we preserve the invariants documented at the top of this file. And we must + * handle out-of-memory errors gracefully (without leaving the graph + * inconsistent), which adds to the fun. */ -// The state used by the freeze operation (shared across many functions). +/* The state used by the freeze operation (shared across many functions). */ typedef struct { int depth; int maxdepth; uint64_t index; - // Maps upb_refcounted* -> attributes (color, etc). attr layout varies by - // color. + /* Maps upb_refcounted* -> attributes (color, etc). attr layout varies by + * color. */ upb_inttable objattr; - upb_inttable stack; // stack of upb_refcounted* for Tarjan's algorithm. - upb_inttable groups; // array of uint32_t*, malloc'd refcounts for new groups + upb_inttable stack; /* stack of upb_refcounted* for Tarjan's algorithm. */ + upb_inttable groups; /* array of uint32_t*, malloc'd refcounts for new groups */ upb_status *status; jmp_buf err; } tarjan; @@ -3066,15 +3017,15 @@ static void release_ref2(const upb_refcounted *obj, const upb_refcounted *subobj, void *closure); -// Node attributes ///////////////////////////////////////////////////////////// +/* Node attributes -----------------------------------------------------------*/ -// After our analysis phase all nodes will be either GRAY or WHITE. +/* After our analysis phase all nodes will be either GRAY or WHITE. */ typedef enum { - BLACK = 0, // Object has not been seen. - GRAY, // Object has been found via a refgroup but may not be reachable. - GREEN, // Object is reachable and is currently on the Tarjan stack. - WHITE, // Object is reachable and has been assigned a group (SCC). + BLACK = 0, /* Object has not been seen. */ + GRAY, /* Object has been found via a refgroup but may not be reachable. */ + GREEN, /* Object is reachable and is currently on the Tarjan stack. */ + WHITE /* Object is reachable and has been assigned a group (SCC). */ } color_t; UPB_NORETURN static void err(tarjan *t) { longjmp(t->err, 1); } @@ -3102,7 +3053,7 @@ static void setattr(tarjan *t, const upb_refcounted *r, uint64_t attr) { } static color_t color(tarjan *t, const upb_refcounted *r) { - return trygetattr(t, r) & 0x3; // Color is always stored in the low 2 bits. + return trygetattr(t, r) & 0x3; /* Color is always stored in the low 2 bits. */ } static void set_gray(tarjan *t, const upb_refcounted *r) { @@ -3110,11 +3061,11 @@ static void set_gray(tarjan *t, const upb_refcounted *r) { setattr(t, r, GRAY); } -// Pushes an obj onto the Tarjan stack and sets it to GREEN. +/* Pushes an obj onto the Tarjan stack and sets it to GREEN. */ static void push(tarjan *t, const upb_refcounted *r) { assert(color(t, r) == BLACK || color(t, r) == GRAY); - // This defines the attr layout for the GREEN state. "index" and "lowlink" - // get 31 bits, which is plenty (limit of 2B objects frozen at a time). + /* This defines the attr layout for the GREEN state. "index" and "lowlink" + * get 31 bits, which is plenty (limit of 2B objects frozen at a time). */ setattr(t, r, GREEN | (t->index << 2) | (t->index << 33)); if (++t->index == 0x80000000) { upb_status_seterrmsg(t->status, "too many objects to freeze"); @@ -3123,13 +3074,13 @@ static void push(tarjan *t, const upb_refcounted *r) { upb_inttable_push(&t->stack, upb_value_ptr((void*)r)); } -// Pops an obj from the Tarjan stack and sets it to WHITE, with a ptr to its -// SCC group. +/* Pops an obj from the Tarjan stack and sets it to WHITE, with a ptr to its + * SCC group. */ static upb_refcounted *pop(tarjan *t) { upb_refcounted *r = upb_value_getptr(upb_inttable_pop(&t->stack)); assert(color(t, r) == GREEN); - // This defines the attr layout for nodes in the WHITE state. - // Top of group stack is [group, NULL]; we point at group. + /* This defines the attr layout for nodes in the WHITE state. + * Top of group stack is [group, NULL]; we point at group. */ setattr(t, r, WHITE | (upb_inttable_count(&t->groups) - 2) << 8); return r; } @@ -3137,7 +3088,7 @@ static upb_refcounted *pop(tarjan *t) { static void tarjan_newgroup(tarjan *t) { uint32_t *group = malloc(sizeof(*group)); if (!group) oom(t); - // Push group and empty group leader (we'll fill in leader later). + /* Push group and empty group leader (we'll fill in leader later). */ if (!upb_inttable_push(&t->groups, upb_value_ptr(group)) || !upb_inttable_push(&t->groups, upb_value_ptr(NULL))) { free(group); @@ -3165,21 +3116,27 @@ static void set_lowlink(tarjan *t, const upb_refcounted *r, uint32_t lowlink) { } static uint32_t *group(tarjan *t, upb_refcounted *r) { - assert(color(t, r) == WHITE); - uint64_t groupnum = getattr(t, r) >> 8; + uint64_t groupnum; upb_value v; - bool found = upb_inttable_lookup(&t->groups, groupnum, &v); + bool found; + + assert(color(t, r) == WHITE); + groupnum = getattr(t, r) >> 8; + found = upb_inttable_lookup(&t->groups, groupnum, &v); UPB_ASSERT_VAR(found, found); return upb_value_getptr(v); } -// If the group leader for this object's group has not previously been set, -// the given object is assigned to be its leader. +/* If the group leader for this object's group has not previously been set, + * the given object is assigned to be its leader. */ static upb_refcounted *groupleader(tarjan *t, upb_refcounted *r) { - assert(color(t, r) == WHITE); - uint64_t leader_slot = (getattr(t, r) >> 8) + 1; + uint64_t leader_slot; upb_value v; - bool found = upb_inttable_lookup(&t->groups, leader_slot, &v); + bool found; + + assert(color(t, r) == WHITE); + leader_slot = (getattr(t, r) >> 8) + 1; + found = upb_inttable_lookup(&t->groups, leader_slot, &v); UPB_ASSERT_VAR(found, found); if (upb_value_getptr(v)) { return upb_value_getptr(v); @@ -3191,10 +3148,10 @@ static upb_refcounted *groupleader(tarjan *t, upb_refcounted *r) { } -// Tarjan's algorithm ////////////////////////////////////////////////////////// +/* Tarjan's algorithm --------------------------------------------------------*/ -// See: -// http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm +/* See: + * http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm */ static void do_tarjan(const upb_refcounted *obj, tarjan *t); static void tarjan_visit(const upb_refcounted *obj, @@ -3205,14 +3162,14 @@ static void tarjan_visit(const upb_refcounted *obj, upb_status_seterrf(t->status, "graph too deep to freeze (%d)", t->maxdepth); err(t); } else if (subobj->is_frozen || color(t, subobj) == WHITE) { - // Do nothing: we don't want to visit or color already-frozen nodes, - // and WHITE nodes have already been assigned a SCC. + /* Do nothing: we don't want to visit or color already-frozen nodes, + * and WHITE nodes have already been assigned a SCC. */ } else if (color(t, subobj) < GREEN) { - // Subdef has not yet been visited; recurse on it. + /* Subdef has not yet been visited; recurse on it. */ do_tarjan(subobj, t); set_lowlink(t, obj, UPB_MIN(lowlink(t, obj), lowlink(t, subobj))); } else if (color(t, subobj) == GREEN) { - // Subdef is in the stack and hence in the current SCC. + /* Subdef is in the stack and hence in the current SCC. */ set_lowlink(t, obj, UPB_MIN(lowlink(t, obj), idx(t, subobj))); } --t->depth; @@ -3220,7 +3177,7 @@ static void tarjan_visit(const upb_refcounted *obj, static void do_tarjan(const upb_refcounted *obj, tarjan *t) { if (color(t, obj) == BLACK) { - // We haven't seen this object's group; mark the whole group GRAY. + /* We haven't seen this object's group; mark the whole group GRAY. */ const upb_refcounted *o = obj; do { set_gray(t, o); } while ((o = o->next) != obj); } @@ -3235,15 +3192,15 @@ static void do_tarjan(const upb_refcounted *obj, tarjan *t) { } -// freeze() //////////////////////////////////////////////////////////////////// +/* freeze() ------------------------------------------------------------------*/ static void crossref(const upb_refcounted *r, const upb_refcounted *subobj, void *_t) { tarjan *t = _t; assert(color(t, r) > BLACK); if (color(t, subobj) > BLACK && r->group != subobj->group) { - // Previously this ref was not reflected in subobj->group because they - // were in the same group; now that they are split a ref must be taken. + /* Previously this ref was not reflected in subobj->group because they + * were in the same group; now that they are split a ref must be taken. */ refgroup(subobj->group); } } @@ -3251,10 +3208,12 @@ static void crossref(const upb_refcounted *r, const upb_refcounted *subobj, static bool freeze(upb_refcounted *const*roots, int n, upb_status *s, int maxdepth) { volatile bool ret = false; + int i; + upb_inttable_iter iter; - // We run in two passes so that we can allocate all memory before performing - // any mutation of the input -- this allows us to leave the input unchanged - // in the case of memory allocation failure. + /* We run in two passes so that we can allocate all memory before performing + * any mutation of the input -- this allows us to leave the input unchanged + * in the case of memory allocation failure. */ tarjan t; t.index = 0; t.depth = 0; @@ -3266,64 +3225,65 @@ static bool freeze(upb_refcounted *const*roots, int n, upb_status *s, if (setjmp(t.err) != 0) goto err4; - for (int i = 0; i < n; i++) { + for (i = 0; i < n; i++) { if (color(&t, roots[i]) < GREEN) { do_tarjan(roots[i], &t); } } - // If we've made it this far, no further errors are possible so it's safe to - // mutate the objects without risk of leaving them in an inconsistent state. + /* If we've made it this far, no further errors are possible so it's safe to + * mutate the objects without risk of leaving them in an inconsistent state. */ ret = true; - // The transformation that follows requires care. The preconditions are: - // - all objects in attr map are WHITE or GRAY, and are in mutable groups - // (groups of all mutable objs) - // - no ref2(to, from) refs have incremented count(to) if both "to" and - // "from" are in our attr map (this follows from invariants (2) and (3)) - - // Pass 1: we remove WHITE objects from their mutable groups, and add them to - // new groups according to the SCC's we computed. These new groups will - // consist of only frozen objects. None will be immediately collectible, - // because WHITE objects are by definition reachable from one of "roots", - // which the caller must own refs on. - upb_inttable_iter i; - upb_inttable_begin(&i, &t.objattr); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&i); - // Since removal from a singly-linked list requires access to the object's - // predecessor, we consider obj->next instead of obj for moving. With the - // while() loop we guarantee that we will visit every node's predecessor. - // Proof: - // 1. every node's predecessor is in our attr map. - // 2. though the loop body may change a node's predecessor, it will only - // change it to be the node we are currently operating on, so with a - // while() loop we guarantee ourselves the chance to remove each node. + /* The transformation that follows requires care. The preconditions are: + * - all objects in attr map are WHITE or GRAY, and are in mutable groups + * (groups of all mutable objs) + * - no ref2(to, from) refs have incremented count(to) if both "to" and + * "from" are in our attr map (this follows from invariants (2) and (3)) */ + + /* Pass 1: we remove WHITE objects from their mutable groups, and add them to + * new groups according to the SCC's we computed. These new groups will + * consist of only frozen objects. None will be immediately collectible, + * because WHITE objects are by definition reachable from one of "roots", + * which the caller must own refs on. */ + upb_inttable_begin(&iter, &t.objattr); + for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) { + upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter); + /* Since removal from a singly-linked list requires access to the object's + * predecessor, we consider obj->next instead of obj for moving. With the + * while() loop we guarantee that we will visit every node's predecessor. + * Proof: + * 1. every node's predecessor is in our attr map. + * 2. though the loop body may change a node's predecessor, it will only + * change it to be the node we are currently operating on, so with a + * while() loop we guarantee ourselves the chance to remove each node. */ while (color(&t, obj->next) == WHITE && group(&t, obj->next) != obj->next->group) { - // Remove from old group. + upb_refcounted *leader; + + /* Remove from old group. */ upb_refcounted *move = obj->next; if (obj == move) { - // Removing the last object from a group. + /* Removing the last object from a group. */ assert(*obj->group == obj->individual_count); free(obj->group); } else { obj->next = move->next; - // This may decrease to zero; we'll collect GRAY objects (if any) that - // remain in the group in the third pass. + /* This may decrease to zero; we'll collect GRAY objects (if any) that + * remain in the group in the third pass. */ assert(*move->group >= move->individual_count); *move->group -= move->individual_count; } - // Add to new group. - upb_refcounted *leader = groupleader(&t, move); + /* Add to new group. */ + leader = groupleader(&t, move); if (move == leader) { - // First object added to new group is its leader. + /* First object added to new group is its leader. */ move->group = group(&t, move); move->next = move; *move->group = move->individual_count; } else { - // Group already has at least one object in it. + /* Group already has at least one object in it. */ assert(leader->group == group(&t, move)); move->group = group(&t, move); move->next = leader->next; @@ -3335,40 +3295,42 @@ static bool freeze(upb_refcounted *const*roots, int n, upb_status *s, } } - // Pass 2: GRAY and WHITE objects "obj" with ref2(to, obj) references must - // increment count(to) if group(obj) != group(to) (which could now be the - // case if "to" was just frozen). - upb_inttable_begin(&i, &t.objattr); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&i); + /* Pass 2: GRAY and WHITE objects "obj" with ref2(to, obj) references must + * increment count(to) if group(obj) != group(to) (which could now be the + * case if "to" was just frozen). */ + upb_inttable_begin(&iter, &t.objattr); + for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) { + upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter); visit(obj, crossref, &t); } - // Pass 3: GRAY objects are collected if their group's refcount dropped to - // zero when we removed its white nodes. This can happen if they had only - // been kept alive by virtue of sharing a group with an object that was just - // frozen. - // - // It is important that we do this last, since the GRAY object's free() - // function could call unref2() on just-frozen objects, which will decrement - // refs that were added in pass 2. - upb_inttable_begin(&i, &t.objattr); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&i); + /* Pass 3: GRAY objects are collected if their group's refcount dropped to + * zero when we removed its white nodes. This can happen if they had only + * been kept alive by virtue of sharing a group with an object that was just + * frozen. + * + * It is important that we do this last, since the GRAY object's free() + * function could call unref2() on just-frozen objects, which will decrement + * refs that were added in pass 2. */ + upb_inttable_begin(&iter, &t.objattr); + for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) { + upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter); if (obj->group == NULL || *obj->group == 0) { if (obj->group) { - // We eagerly free() the group's count (since we can't easily determine - // the group's remaining size it's the easiest way to ensure it gets - // done). + upb_refcounted *o; + + /* We eagerly free() the group's count (since we can't easily determine + * the group's remaining size it's the easiest way to ensure it gets + * done). */ free(obj->group); - // Visit to release ref2's (done in a separate pass since release_ref2 - // depends on o->group being unmodified so it can test merged()). - upb_refcounted *o = obj; + /* Visit to release ref2's (done in a separate pass since release_ref2 + * depends on o->group being unmodified so it can test merged()). */ + o = obj; do { visit(o, release_ref2, NULL); } while ((o = o->next) != obj); - // Mark "group" fields as NULL so we know to free the objects later in - // this loop, but also don't try to delete the group twice. + /* Mark "group" fields as NULL so we know to free the objects later in + * this loop, but also don't try to delete the group twice. */ o = obj; do { o->group = NULL; } while ((o = o->next) != obj); } @@ -3378,9 +3340,9 @@ static bool freeze(upb_refcounted *const*roots, int n, upb_status *s, err4: if (!ret) { - upb_inttable_begin(&i, &t.groups); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) - free(upb_value_getptr(upb_inttable_iter_value(&i))); + upb_inttable_begin(&iter, &t.groups); + for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) + free(upb_value_getptr(upb_inttable_iter_value(&iter))); } upb_inttable_uninit(&t.groups); err3: @@ -3399,21 +3361,24 @@ static bool merged(const upb_refcounted *r, const upb_refcounted *r2) { } static void merge(upb_refcounted *r, upb_refcounted *from) { + upb_refcounted *base; + upb_refcounted *tmp; + if (merged(r, from)) return; *r->group += *from->group; free(from->group); - upb_refcounted *base = from; - - // Set all refcount pointers in the "from" chain to the merged refcount. - // - // TODO(haberman): this linear algorithm can result in an overall O(n^2) bound - // if the user continuously extends a group by one object. Prevent this by - // using one of the techniques in this paper: - // ftp://www.ncedc.org/outgoing/geomorph/dino/orals/p245-tarjan.pdf + base = from; + + /* Set all refcount pointers in the "from" chain to the merged refcount. + * + * TODO(haberman): this linear algorithm can result in an overall O(n^2) bound + * if the user continuously extends a group by one object. Prevent this by + * using one of the techniques in this paper: + * ftp://www.ncedc.org/outgoing/geomorph/dino/orals/p245-tarjan.pdf */ do { from->group = r->group; } while ((from = from->next) != base); - // Merge the two circularly linked lists by swapping their next pointers. - upb_refcounted *tmp = r->next; + /* Merge the two circularly linked lists by swapping their next pointers. */ + tmp = r->next; r->next = base->next; base->next = tmp; } @@ -3433,11 +3398,13 @@ static void release_ref2(const upb_refcounted *obj, static void unref(const upb_refcounted *r) { if (unrefgroup(r->group)) { + const upb_refcounted *o; + free(r->group); - // In two passes, since release_ref2 needs a guarantee that any subobjs - // are alive. - const upb_refcounted *o = r; + /* In two passes, since release_ref2 needs a guarantee that any subobjs + * are alive. */ + o = r; do { visit(o, release_ref2, NULL); } while((o = o->next) != r); o = r; @@ -3461,6 +3428,18 @@ static void freeobj(upb_refcounted *o) { bool upb_refcounted_init(upb_refcounted *r, const struct upb_refcounted_vtbl *vtbl, const void *owner) { +#ifndef NDEBUG + /* Endianness check. This is unrelated to upb_refcounted, it's just a + * convenient place to put the check that we can be assured will run for + * basically every program using upb. */ + const int x = 1; +#ifdef UPB_BIG_ENDIAN + assert(*(char*)&x != 1); +#else + assert(*(char*)&x == 1); +#endif +#endif + r->next = r; r->vtbl = vtbl; r->individual_count = 0; @@ -3495,7 +3474,7 @@ void upb_refcounted_unref(const upb_refcounted *r, const void *owner) { } void upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from) { - assert(!from->is_frozen); // Non-const pointer implies this. + assert(!from->is_frozen); /* Non-const pointer implies this. */ track(r, from, true); if (r->is_frozen) { refgroup(r->group); @@ -3505,7 +3484,7 @@ void upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from) { } void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from) { - assert(!from->is_frozen); // Non-const pointer implies this. + assert(!from->is_frozen); /* Non-const pointer implies this. */ untrack(r, from, true); if (r->is_frozen) { unref(r); @@ -3529,7 +3508,8 @@ void upb_refcounted_checkref(const upb_refcounted *r, const void *owner) { bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s, int maxdepth) { - for (int i = 0; i < n; i++) { + int i; + for (i = 0; i < n; i++) { assert(!roots[i]->is_frozen); } return freeze(roots, n, s, maxdepth); @@ -3544,7 +3524,7 @@ bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s, #include <stdlib.h> -// Fallback implementation if the shim is not specialized by the JIT. +/* Fallback implementation if the shim is not specialized by the JIT. */ #define SHIM_WRITER(type, ctype) \ bool upb_shim_set ## type (void *c, const void *hd, ctype val) { \ uint8_t *m = c; \ @@ -3566,12 +3546,14 @@ SHIM_WRITER(bool, bool) bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset, int32_t hasbit) { + upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; + bool ok; + upb_shim_data *d = malloc(sizeof(*d)); if (!d) return false; d->offset = offset; d->hasbit = hasbit; - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; upb_handlerattr_sethandlerdata(&attr, d); upb_handlerattr_setalwaysok(&attr, true); upb_handlers_addcleanup(h, d, free); @@ -3580,7 +3562,7 @@ bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset, case UPB_TYPE_##u: \ ok = upb_handlers_set##l(h, f, upb_shim_set##l, &attr); break; - bool ok = false; + ok = false; switch (upb_fielddef_type(f)) { TYPE(INT64, int64); @@ -3634,27 +3616,6 @@ const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s, #include <stdlib.h> #include <string.h> -bool upb_symtab_isfrozen(const upb_symtab *s) { - return upb_refcounted_isfrozen(UPB_UPCAST(s)); -} - -void upb_symtab_ref(const upb_symtab *s, const void *owner) { - upb_refcounted_ref(UPB_UPCAST(s), owner); -} - -void upb_symtab_unref(const upb_symtab *s, const void *owner) { - upb_refcounted_unref(UPB_UPCAST(s), owner); -} - -void upb_symtab_donateref( - const upb_symtab *s, const void *from, const void *to) { - upb_refcounted_donateref(UPB_UPCAST(s), from, to); -} - -void upb_symtab_checkref(const upb_symtab *s, const void *owner) { - upb_refcounted_checkref(UPB_UPCAST(s), owner); -} - static void upb_symtab_free(upb_refcounted *r) { upb_symtab *s = (upb_symtab*)r; upb_strtable_iter i; @@ -3671,18 +3632,21 @@ static void upb_symtab_free(upb_refcounted *r) { upb_symtab *upb_symtab_new(const void *owner) { static const struct upb_refcounted_vtbl vtbl = {NULL, &upb_symtab_free}; upb_symtab *s = malloc(sizeof(*s)); - upb_refcounted_init(UPB_UPCAST(s), &vtbl, owner); + upb_refcounted_init(upb_symtab_upcast_mutable(s), &vtbl, owner); upb_strtable_init(&s->symtab, UPB_CTYPE_PTR); return s; } void upb_symtab_freeze(upb_symtab *s) { + upb_refcounted *r; + bool ok; + assert(!upb_symtab_isfrozen(s)); - upb_refcounted *r = UPB_UPCAST(s); - // The symtab does not take ref2's (see refcounted.h) on the defs, because - // defs cannot refer back to the table and therefore cannot create cycles. So - // 0 will suffice for maxdepth here. - bool ok = upb_refcounted_freeze(&r, 1, NULL, 0); + r = upb_symtab_upcast_mutable(s); + /* The symtab does not take ref2's (see refcounted.h) on the defs, because + * defs cannot refer back to the table and therefore cannot create cycles. So + * 0 will suffice for maxdepth here. */ + ok = upb_refcounted_freeze(&r, 1, NULL, 0); UPB_ASSERT_VAR(ok, ok); } @@ -3707,19 +3671,19 @@ const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) { return def ? upb_dyncast_enumdef(def) : NULL; } -// Given a symbol and the base symbol inside which it is defined, find the -// symbol's definition in t. +/* Given a symbol and the base symbol inside which it is defined, find the + * symbol's definition in t. */ static upb_def *upb_resolvename(const upb_strtable *t, const char *base, const char *sym) { if(strlen(sym) == 0) return NULL; if(sym[0] == '.') { - // Symbols starting with '.' are absolute, so we do a single lookup. - // Slice to omit the leading '.' + /* Symbols starting with '.' are absolute, so we do a single lookup. + * Slice to omit the leading '.' */ upb_value v; return upb_strtable_lookup(t, sym + 1, &v) ? upb_value_getptr(v) : NULL; } else { - // Remove components from base until we find an entry or run out. - // TODO: This branch is totally broken, but currently not used. + /* Remove components from base until we find an entry or run out. + * TODO: This branch is totally broken, but currently not used. */ (void)base; assert(false); return NULL; @@ -3732,57 +3696,95 @@ const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base, return ret; } -// Searches def and its children to find defs that have the same name as any -// def in "addtab." Returns true if any where found, and as a side-effect adds -// duplicates of these defs into addtab. -// -// We use a modified depth-first traversal that traverses each SCC (which we -// already computed) as if it were a single node. This allows us to traverse -// the possibly-cyclic graph as if it were a DAG and to dup the correct set of -// nodes with O(n) time. +/* Starts a depth-first traversal at "def", recursing into any subdefs + * (ie. submessage types). Adds duplicates of existing defs to addtab + * wherever necessary, so that the resulting symtab will be consistent once + * addtab is added. + * + * More specifically, if any def D is found in the DFS that: + * + * 1. can reach a def that is being replaced by something in addtab, AND + * + * 2. is not itself being replaced already (ie. this name doesn't already + * exist in addtab) + * + * ...then a duplicate (new copy) of D will be added to addtab. + * + * Returns true if this happened for any def reachable from "def." + * + * It is slightly tricky to do this correctly in the presence of cycles. If we + * detect that our DFS has hit a cycle, we might not yet know if any SCCs on + * our stack can reach a def in addtab or not. Once we figure this out, that + * answer needs to apply to *all* defs in these SCCs, even if we visited them + * already. So a straight up one-pass cycle-detecting DFS won't work. + * + * To work around this problem, we traverse each SCC (which we already + * computed, since these defs are frozen) as a single node. We first compute + * whether the SCC as a whole can reach any def in addtab, then we dup (or not) + * the entire SCC. This requires breaking the encapsulation of upb_refcounted, + * since that is where we get the data about what SCC we are in. */ static bool upb_resolve_dfs(const upb_def *def, upb_strtable *addtab, const void *new_owner, upb_inttable *seen, upb_status *s) { - // Memoize results of this function for efficiency (since we're traversing a - // DAG this is not needed to limit the depth of the search). upb_value v; - if (upb_inttable_lookup(seen, (uintptr_t)def, &v)) + bool need_dup; + const upb_def *base; + const void* memoize_key; + + /* Memoize results of this function for efficiency (since we're traversing a + * DAG this is not needed to limit the depth of the search). + * + * We memoize by SCC instead of by individual def. */ + memoize_key = def->base.group; + + if (upb_inttable_lookupptr(seen, memoize_key, &v)) return upb_value_getbool(v); - // Visit submessages for all messages in the SCC. - bool need_dup = false; - const upb_def *base = def; + /* Visit submessages for all messages in the SCC. */ + need_dup = false; + base = def; do { + upb_value v; + const upb_msgdef *m; + assert(upb_def_isfrozen(def)); if (def->type == UPB_DEF_FIELD) continue; - upb_value v; if (upb_strtable_lookup(addtab, upb_def_fullname(def), &v)) { need_dup = true; } - // For messages, continue the recursion by visiting all subdefs. - const upb_msgdef *m = upb_dyncast_msgdef(def); + /* For messages, continue the recursion by visiting all subdefs, but only + * ones in different SCCs. */ + m = upb_dyncast_msgdef(def); if (m) { upb_msg_field_iter i; for(upb_msg_field_begin(&i, m); !upb_msg_field_done(&i); upb_msg_field_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); + const upb_def *subdef; + if (!upb_fielddef_hassubdef(f)) continue; - // |= to avoid short-circuit; we need its side-effects. - need_dup |= upb_resolve_dfs( - upb_fielddef_subdef(f), addtab, new_owner, seen, s); + subdef = upb_fielddef_subdef(f); + + /* Skip subdefs in this SCC. */ + if (def->base.group == subdef->base.group) continue; + + /* |= to avoid short-circuit; we need its side-effects. */ + need_dup |= upb_resolve_dfs(subdef, addtab, new_owner, seen, s); if (!upb_ok(s)) return false; } } } while ((def = (upb_def*)def->base.next) != base); if (need_dup) { - // Dup any defs that don't already have entries in addtab. + /* Dup all defs in this SCC that don't already have entries in addtab. */ def = base; do { + const char *name; + if (def->type == UPB_DEF_FIELD) continue; - const char *name = upb_def_fullname(def); + name = upb_def_fullname(def); if (!upb_strtable_lookup(addtab, name, NULL)) { upb_def *newdef = upb_def_dup(def, new_owner); if (!newdef) goto oom; @@ -3793,7 +3795,7 @@ static bool upb_resolve_dfs(const upb_def *def, upb_strtable *addtab, } while ((def = (upb_def*)def->base.next) != base); } - upb_inttable_insert(seen, (uintptr_t)def, upb_value_bool(need_dup)); + upb_inttable_insertptr(seen, memoize_key, upb_value_bool(need_dup)); return need_dup; oom: @@ -3801,34 +3803,41 @@ oom: return false; } -// TODO(haberman): we need a lot more testing of error conditions. -// The came_from_user stuff in particular is not tested. +/* TODO(haberman): we need a lot more testing of error conditions. + * The came_from_user stuff in particular is not tested. */ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor, upb_status *status) { - assert(!upb_symtab_isfrozen(s)); + int i; + upb_strtable_iter iter; upb_def **add_defs = NULL; upb_strtable addtab; + upb_inttable seen; + + assert(!upb_symtab_isfrozen(s)); if (!upb_strtable_init(&addtab, UPB_CTYPE_PTR)) { upb_status_seterrmsg(status, "out of memory"); return false; } - // Add new defs to our "add" set. - for (int i = 0; i < n; i++) { + /* Add new defs to our "add" set. */ + for (i = 0; i < n; i++) { upb_def *def = defs[i]; + const char *fullname; + upb_fielddef *f; + if (upb_def_isfrozen(def)) { upb_status_seterrmsg(status, "added defs must be mutable"); goto err; } assert(!upb_def_isfrozen(def)); - const char *fullname = upb_def_fullname(def); + fullname = upb_def_fullname(def); if (!fullname) { upb_status_seterrmsg( status, "Anonymous defs cannot be added to a symtab"); goto err; } - upb_fielddef *f = upb_dyncast_fielddef_mutable(def); + f = upb_dyncast_fielddef_mutable(def); if (f) { if (!upb_fielddef_containingtypename(f)) { @@ -3842,8 +3851,8 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor, upb_status_seterrf(status, "Conflicting defs named '%s'", fullname); goto err; } - // We need this to back out properly, because if there is a failure we - // need to donate the ref back to the caller. + /* We need this to back out properly, because if there is a failure we + * need to donate the ref back to the caller. */ def->came_from_user = true; upb_def_donateref(def, ref_donor, s); if (!upb_strtable_insert(&addtab, fullname, upb_value_ptr(def))) @@ -3851,31 +3860,33 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor, } } - // Add standalone fielddefs (ie. extensions) to the appropriate messages. - // If the appropriate message only exists in the existing symtab, duplicate - // it so we have a mutable copy we can add the fields to. - for (int i = 0; i < n; i++) { + /* Add standalone fielddefs (ie. extensions) to the appropriate messages. + * If the appropriate message only exists in the existing symtab, duplicate + * it so we have a mutable copy we can add the fields to. */ + for (i = 0; i < n; i++) { upb_def *def = defs[i]; upb_fielddef *f = upb_dyncast_fielddef_mutable(def); + const char *msgname; + upb_value v; + upb_msgdef *m; + if (!f) continue; - const char *msgname = upb_fielddef_containingtypename(f); - // We validated this earlier in this function. + msgname = upb_fielddef_containingtypename(f); + /* We validated this earlier in this function. */ assert(msgname); - // If the extendee name is absolutely qualified, move past the initial ".". - // TODO(haberman): it is not obvious what it would mean if this was not - // absolutely qualified. + /* If the extendee name is absolutely qualified, move past the initial ".". + * TODO(haberman): it is not obvious what it would mean if this was not + * absolutely qualified. */ if (msgname[0] == '.') { msgname++; } - upb_value v; - upb_msgdef *m; if (upb_strtable_lookup(&addtab, msgname, &v)) { - // Extendee is in the set of defs the user asked us to add. + /* Extendee is in the set of defs the user asked us to add. */ m = upb_value_getptr(v); } else { - // Need to find and dup the extendee from the existing symtab. + /* Need to find and dup the extendee from the existing symtab. */ const upb_msgdef *frozen_m = upb_symtab_lookupmsg(s, msgname); if (!frozen_m) { upb_status_seterrf(status, @@ -3897,37 +3908,37 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor, } } - // Add dups of any existing def that can reach a def with the same name as - // anything in our "add" set. - upb_inttable seen; + /* Add dups of any existing def that can reach a def with the same name as + * anything in our "add" set. */ if (!upb_inttable_init(&seen, UPB_CTYPE_BOOL)) goto oom_err; - upb_strtable_iter i; - upb_strtable_begin(&i, &s->symtab); - for (; !upb_strtable_done(&i); upb_strtable_next(&i)) { - upb_def *def = upb_value_getptr(upb_strtable_iter_value(&i)); + upb_strtable_begin(&iter, &s->symtab); + for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) { + upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter)); upb_resolve_dfs(def, &addtab, s, &seen, status); if (!upb_ok(status)) goto err; } upb_inttable_uninit(&seen); - // Now using the table, resolve symbolic references for subdefs. - upb_strtable_begin(&i, &addtab); - for (; !upb_strtable_done(&i); upb_strtable_next(&i)) { - upb_def *def = upb_value_getptr(upb_strtable_iter_value(&i)); + /* Now using the table, resolve symbolic references for subdefs. */ + upb_strtable_begin(&iter, &addtab); + for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) { + const char *base; + upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter)); upb_msgdef *m = upb_dyncast_msgdef_mutable(def); + upb_msg_field_iter j; + if (!m) continue; - // Type names are resolved relative to the message in which they appear. - const char *base = upb_msgdef_fullname(m); + /* Type names are resolved relative to the message in which they appear. */ + base = upb_msgdef_fullname(m); - upb_msg_field_iter j; for(upb_msg_field_begin(&j, m); !upb_msg_field_done(&j); upb_msg_field_next(&j)) { upb_fielddef *f = upb_msg_iter_field(&j); const char *name = upb_fielddef_subdefname(f); if (name && !upb_fielddef_subdef(f)) { - // Try the lookup in the current set of to-be-added defs first. If not - // there, try existing defs. + /* Try the lookup in the current set of to-be-added defs first. If not + * there, try existing defs. */ upb_def *subdef = upb_resolvename(&addtab, base, name); if (subdef == NULL) { subdef = upb_resolvename(&s->symtab, base, name); @@ -3943,31 +3954,33 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor, } } - // We need an array of the defs in addtab, for passing to upb_def_freeze. + /* We need an array of the defs in addtab, for passing to upb_def_freeze. */ add_defs = malloc(sizeof(void*) * upb_strtable_count(&addtab)); if (add_defs == NULL) goto oom_err; - upb_strtable_begin(&i, &addtab); - for (n = 0; !upb_strtable_done(&i); upb_strtable_next(&i)) { - add_defs[n++] = upb_value_getptr(upb_strtable_iter_value(&i)); + upb_strtable_begin(&iter, &addtab); + for (n = 0; !upb_strtable_done(&iter); upb_strtable_next(&iter)) { + add_defs[n++] = upb_value_getptr(upb_strtable_iter_value(&iter)); } if (!upb_def_freeze(add_defs, n, status)) goto err; - // This must be delayed until all errors have been detected, since error - // recovery code uses this table to cleanup defs. + /* This must be delayed until all errors have been detected, since error + * recovery code uses this table to cleanup defs. */ upb_strtable_uninit(&addtab); - // TODO(haberman) we don't properly handle errors after this point (like - // OOM in upb_strtable_insert() below). - for (int i = 0; i < n; i++) { + /* TODO(haberman) we don't properly handle errors after this point (like + * OOM in upb_strtable_insert() below). */ + for (i = 0; i < n; i++) { upb_def *def = add_defs[i]; const char *name = upb_def_fullname(def); upb_value v; + bool success; + if (upb_strtable_remove(&s->symtab, name, &v)) { const upb_def *def = upb_value_getptr(v); upb_def_unref(def, s); } - bool success = upb_strtable_insert(&s->symtab, name, upb_value_ptr(def)); + success = upb_strtable_insert(&s->symtab, name, upb_value_ptr(def)); UPB_ASSERT_VAR(success, success == true); } free(add_defs); @@ -3976,12 +3989,11 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor, oom_err: upb_status_seterrmsg(status, "out of memory"); err: { - // For defs the user passed in, we need to donate the refs back. For defs - // we dup'd, we need to just unref them. - upb_strtable_iter i; - upb_strtable_begin(&i, &addtab); - for (; !upb_strtable_done(&i); upb_strtable_next(&i)) { - upb_def *def = upb_value_getptr(upb_strtable_iter_value(&i)); + /* For defs the user passed in, we need to donate the refs back. For defs + * we dup'd, we need to just unref them. */ + upb_strtable_begin(&iter, &addtab); + for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) { + upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter)); bool came_from_user = def->came_from_user; def->came_from_user = false; if (came_from_user) { @@ -3997,7 +4009,7 @@ err: { return false; } -// Iteration. +/* Iteration. */ static void advance_to_matching(upb_symtab_iter *iter) { if (iter->type == UPB_DEF_ANY) @@ -4041,17 +4053,17 @@ const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter) { #include <stdlib.h> #include <string.h> -#define UPB_MAXARRSIZE 16 // 64k. +#define UPB_MAXARRSIZE 16 /* 64k. */ -// From Chromium. +/* From Chromium. */ #define ARRAY_SIZE(x) \ ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) static const double MAX_LOAD = 0.85; -// The minimum utilization of the array part of a mixed hash/array table. This -// is a speed/memory-usage tradeoff (though it's not straightforward because of -// cache effects). The lower this is, the more memory we'll use. +/* The minimum utilization of the array part of a mixed hash/array table. This + * is a speed/memory-usage tradeoff (though it's not straightforward because of + * cache effects). The lower this is, the more memory we'll use. */ static const double MIN_DENSITY = 0.1; bool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; } @@ -4060,7 +4072,7 @@ int log2ceil(uint64_t v) { int ret = 0; bool pow2 = is_pow2(v); while (v >>= 1) ret++; - ret = pow2 ? ret : ret + 1; // Ceiling. + ret = pow2 ? ret : ret + 1; /* Ceiling. */ return UPB_MIN(UPB_MAXARRSIZE, ret); } @@ -4069,12 +4081,15 @@ char *upb_strdup(const char *s) { } char *upb_strdup2(const char *s, size_t len) { - // Prevent overflow errors. + size_t n; + char *p; + + /* Prevent overflow errors. */ if (len == SIZE_MAX) return NULL; - // Always null-terminate, even if binary data; but don't rely on the input to - // have a null-terminating byte since it may be a raw binary buffer. - size_t n = len + 1; - char *p = malloc(n); + /* Always null-terminate, even if binary data; but don't rely on the input to + * have a null-terminating byte since it may be a raw binary buffer. */ + n = len + 1; + p = malloc(n); if (p) { memcpy(p, s, len); p[len] = 0; @@ -4082,21 +4097,25 @@ char *upb_strdup2(const char *s, size_t len) { return p; } -// A type to represent the lookup key of either a strtable or an inttable. -typedef struct { - upb_tabkey key; +/* A type to represent the lookup key of either a strtable or an inttable. */ +typedef union { + uintptr_t num; + struct { + const char *str; + size_t len; + } str; } lookupkey_t; static lookupkey_t strkey2(const char *str, size_t len) { lookupkey_t k; - k.key.s.str = (char*)str; - k.key.s.length = len; + k.str.str = str; + k.str.len = len; return k; } static lookupkey_t intkey(uintptr_t key) { lookupkey_t k; - k.key = upb_intkey(key); + k.num = key; return k; } @@ -4105,7 +4124,7 @@ typedef bool eqlfunc_t(upb_tabkey k1, lookupkey_t k2); /* Base table (shared code) ***************************************************/ -// For when we need to cast away const. +/* For when we need to cast away const. */ static upb_tabent *mutable_entries(upb_table *t) { return (upb_tabent*)t->entries; } @@ -4115,11 +4134,13 @@ static bool isfull(upb_table *t) { } static bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2) { + size_t bytes; + t->count = 0; t->ctype = ctype; t->size_lg2 = size_lg2; t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0; - size_t bytes = upb_table_size(t) * sizeof(upb_tabent); + bytes = upb_table_size(t) * sizeof(upb_tabent); if (bytes > 0) { t->entries = malloc(bytes); if (!t->entries) return false; @@ -4143,8 +4164,10 @@ static upb_tabent *getentry_mutable(upb_table *t, uint32_t hash) { static const upb_tabent *findentry(const upb_table *t, lookupkey_t key, uint32_t hash, eqlfunc_t *eql) { + const upb_tabent *e; + if (t->size_lg2 == 0) return NULL; - const upb_tabent *e = upb_getentry(t, hash); + e = upb_getentry(t, hash); if (upb_tabent_isempty(e)) return NULL; while (1) { if (eql(e->key, key)) return e; @@ -4162,7 +4185,7 @@ static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v, const upb_tabent *e = findentry(t, key, hash, eql); if (e) { if (v) { - _upb_value_setval(v, e->val, t->ctype); + _upb_value_setval(v, e->val.val, t->ctype); } return true; } else { @@ -4170,34 +4193,41 @@ static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v, } } -// The given key must not already exist in the table. -static void insert(upb_table *t, lookupkey_t key, upb_value val, - uint32_t hash, hashfunc_t *hashfunc, eqlfunc_t *eql) { +/* The given key must not already exist in the table. */ +static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey, + upb_value val, uint32_t hash, + hashfunc_t *hashfunc, eqlfunc_t *eql) { + upb_tabent *mainpos_e; + upb_tabent *our_e; + UPB_UNUSED(eql); + UPB_UNUSED(key); assert(findentry(t, key, hash, eql) == NULL); assert(val.ctype == t->ctype); + t->count++; - upb_tabent *mainpos_e = getentry_mutable(t, hash); - upb_tabent *our_e = mainpos_e; + mainpos_e = getentry_mutable(t, hash); + our_e = mainpos_e; + if (upb_tabent_isempty(mainpos_e)) { - // Our main position is empty; use it. + /* Our main position is empty; use it. */ our_e->next = NULL; } else { - // Collision. + /* Collision. */ upb_tabent *new_e = emptyent(t); - // Head of collider's chain. + /* Head of collider's chain. */ upb_tabent *chain = getentry_mutable(t, hashfunc(mainpos_e->key)); if (chain == mainpos_e) { - // Existing ent is in its main posisiton (it has the same hash as us, and - // is the head of our chain). Insert to new ent and append to this chain. + /* Existing ent is in its main posisiton (it has the same hash as us, and + * is the head of our chain). Insert to new ent and append to this chain. */ new_e->next = mainpos_e->next; mainpos_e->next = new_e; our_e = new_e; } else { - // Existing ent is not in its main position (it is a node in some other - // chain). This implies that no existing ent in the table has our hash. - // Evict it (updating its chain) and use its ent for head of our chain. - *new_e = *mainpos_e; // copies next. + /* Existing ent is not in its main position (it is a node in some other + * chain). This implies that no existing ent in the table has our hash. + * Evict it (updating its chain) and use its ent for head of our chain. */ + *new_e = *mainpos_e; /* copies next. */ while (chain->next != mainpos_e) { chain = (upb_tabent*)chain->next; assert(chain); @@ -4207,8 +4237,8 @@ static void insert(upb_table *t, lookupkey_t key, upb_value val, our_e->next = NULL; } } - our_e->key = key.key; - our_e->val = val.val; + our_e->key = tabkey; + our_e->val.val = val.val; assert(findentry(t, key, hash, eql) == our_e); } @@ -4217,33 +4247,36 @@ static bool rm(upb_table *t, lookupkey_t key, upb_value *val, upb_tabent *chain = getentry_mutable(t, hash); if (upb_tabent_isempty(chain)) return false; if (eql(chain->key, key)) { - // Element to remove is at the head of its chain. + /* Element to remove is at the head of its chain. */ t->count--; if (val) { - _upb_value_setval(val, chain->val, t->ctype); + _upb_value_setval(val, chain->val.val, t->ctype); } if (chain->next) { upb_tabent *move = (upb_tabent*)chain->next; *chain = *move; if (removed) *removed = move->key; - move->key.num = 0; // Make the slot empty. + move->key = 0; /* Make the slot empty. */ } else { if (removed) *removed = chain->key; - chain->key.num = 0; // Make the slot empty. + chain->key = 0; /* Make the slot empty. */ } return true; } else { - // Element to remove is either in a non-head position or not in the table. + /* Element to remove is either in a non-head position or not in the + * table. */ while (chain->next && !eql(chain->next->key, key)) chain = (upb_tabent*)chain->next; if (chain->next) { - // Found element to remove. + /* Found element to remove. */ + upb_tabent *rm; + if (val) { - _upb_value_setval(val, chain->next->val, t->ctype); + _upb_value_setval(val, chain->next->val.val, t->ctype); } - upb_tabent *rm = (upb_tabent*)chain->next; + rm = (upb_tabent*)chain->next; if (removed) *removed = rm->key; - rm->key.num = 0; + rm->key = 0; chain->next = rm->next; t->count--; return true; @@ -4269,15 +4302,26 @@ static size_t begin(const upb_table *t) { /* upb_strtable ***************************************************************/ -// A simple "subclass" of upb_table that only adds a hash function for strings. +/* A simple "subclass" of upb_table that only adds a hash function for strings. */ + +static upb_tabkey strcopy(lookupkey_t k2) { + char *str = malloc(k2.str.len + sizeof(uint32_t) + 1); + if (str == NULL) return 0; + memcpy(str, &k2.str.len, sizeof(uint32_t)); + memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len + 1); + return (uintptr_t)str; +} static uint32_t strhash(upb_tabkey key) { - return MurmurHash2(key.s.str, key.s.length, 0); + uint32_t len; + char *str = upb_tabstr(key, &len); + return MurmurHash2(str, len, 0); } static bool streql(upb_tabkey k1, lookupkey_t k2) { - return k1.s.length == k2.key.s.length && - memcmp(k1.s.str, k2.key.s.str, k1.s.length) == 0; + uint32_t len; + char *str = upb_tabstr(k1, &len); + return len == k2.str.len && memcmp(str, k2.str.str, len) == 0; } bool upb_strtable_init(upb_strtable *t, upb_ctype_t ctype) { @@ -4285,16 +4329,18 @@ bool upb_strtable_init(upb_strtable *t, upb_ctype_t ctype) { } void upb_strtable_uninit(upb_strtable *t) { - for (size_t i = 0; i < upb_table_size(&t->t); i++) - free((void*)t->t.entries[i].key.s.str); + size_t i; + for (i = 0; i < upb_table_size(&t->t); i++) + free((void*)t->t.entries[i].key); uninit(&t->t); } bool upb_strtable_resize(upb_strtable *t, size_t size_lg2) { upb_strtable new_table; + upb_strtable_iter i; + if (!init(&new_table.t, t->t.ctype, size_lg2)) return false; - upb_strtable_iter i; upb_strtable_begin(&i, t); for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) { upb_strtable_insert2( @@ -4310,17 +4356,23 @@ bool upb_strtable_resize(upb_strtable *t, size_t size_lg2) { bool upb_strtable_insert2(upb_strtable *t, const char *k, size_t len, upb_value v) { + lookupkey_t key; + upb_tabkey tabkey; + uint32_t hash; + if (isfull(&t->t)) { - // Need to resize. New table of double the size, add old elements to it. + /* Need to resize. New table of double the size, add old elements to it. */ if (!upb_strtable_resize(t, t->t.size_lg2 + 1)) { return false; } } - if ((k = upb_strdup2(k, len)) == NULL) return false; - lookupkey_t key = strkey2(k, len); - uint32_t hash = MurmurHash2(key.key.s.str, key.key.s.length, 0); - insert(&t->t, key, v, hash, &strhash, &streql); + key = strkey2(k, len); + tabkey = strcopy(key); + if (tabkey == 0) return false; + + hash = MurmurHash2(key.str.str, key.str.len, 0); + insert(&t->t, key, tabkey, v, hash, &strhash, &streql); return true; } @@ -4335,14 +4387,14 @@ bool upb_strtable_remove2(upb_strtable *t, const char *key, size_t len, uint32_t hash = MurmurHash2(key, strlen(key), 0); upb_tabkey tabkey; if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) { - free((void*)tabkey.s.str); + free((void*)tabkey); return true; } else { return false; } } -// Iteration +/* Iteration */ static const upb_tabent *str_tabent(const upb_strtable_iter *i) { return &i->t->t.entries[i->index]; @@ -4364,17 +4416,19 @@ bool upb_strtable_done(const upb_strtable_iter *i) { const char *upb_strtable_iter_key(upb_strtable_iter *i) { assert(!upb_strtable_done(i)); - return str_tabent(i)->key.s.str; + return upb_tabstr(str_tabent(i)->key, NULL); } size_t upb_strtable_iter_keylength(upb_strtable_iter *i) { + uint32_t len; assert(!upb_strtable_done(i)); - return str_tabent(i)->key.s.length; + upb_tabstr(str_tabent(i)->key, &len); + return len; } upb_value upb_strtable_iter_value(const upb_strtable_iter *i) { assert(!upb_strtable_done(i)); - return _upb_value_val(str_tabent(i)->val, i->t->t.ctype); + return _upb_value_val(str_tabent(i)->val.val, i->t->t.ctype); } void upb_strtable_iter_setdone(upb_strtable_iter *i) { @@ -4391,20 +4445,20 @@ bool upb_strtable_iter_isequal(const upb_strtable_iter *i1, /* upb_inttable ***************************************************************/ -// For inttables we use a hybrid structure where small keys are kept in an -// array and large keys are put in the hash table. +/* For inttables we use a hybrid structure where small keys are kept in an + * array and large keys are put in the hash table. */ -static uint32_t inthash(upb_tabkey key) { return upb_inthash(key.num); } +static uint32_t inthash(upb_tabkey key) { return upb_inthash(key); } static bool inteql(upb_tabkey k1, lookupkey_t k2) { - return k1.num == k2.key.num; + return k1 == k2.num; } -static _upb_value *mutable_array(upb_inttable *t) { - return (_upb_value*)t->array; +static upb_tabval *mutable_array(upb_inttable *t) { + return (upb_tabval*)t->array; } -static _upb_value *inttable_val(upb_inttable *t, uintptr_t key) { +static upb_tabval *inttable_val(upb_inttable *t, uintptr_t key) { if (key < t->array_size) { return upb_arrhas(t->array[key]) ? &(mutable_array(t)[key]) : NULL; } else { @@ -4414,7 +4468,7 @@ static _upb_value *inttable_val(upb_inttable *t, uintptr_t key) { } } -static const _upb_value *inttable_val_const(const upb_inttable *t, +static const upb_tabval *inttable_val_const(const upb_inttable *t, uintptr_t key) { return inttable_val((upb_inttable*)t, key); } @@ -4426,25 +4480,29 @@ size_t upb_inttable_count(const upb_inttable *t) { static void check(upb_inttable *t) { UPB_UNUSED(t); #if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG) - // This check is very expensive (makes inserts/deletes O(N)). - size_t count = 0; - upb_inttable_iter i; - upb_inttable_begin(&i, t); - for(; !upb_inttable_done(&i); upb_inttable_next(&i), count++) { - assert(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL)); + { + /* This check is very expensive (makes inserts/deletes O(N)). */ + size_t count = 0; + upb_inttable_iter i; + upb_inttable_begin(&i, t); + for(; !upb_inttable_done(&i); upb_inttable_next(&i), count++) { + assert(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL)); + } + assert(count == upb_inttable_count(t)); } - assert(count == upb_inttable_count(t)); #endif } bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t ctype, size_t asize, int hsize_lg2) { + size_t array_bytes; + if (!init(&t->t, ctype, hsize_lg2)) return false; - // Always make the array part at least 1 long, so that we know key 0 - // won't be in the hash part, which simplifies things. + /* Always make the array part at least 1 long, so that we know key 0 + * won't be in the hash part, which simplifies things. */ t->array_size = UPB_MAX(1, asize); t->array_count = 0; - size_t array_bytes = t->array_size * sizeof(upb_value); + array_bytes = t->array_size * sizeof(upb_value); t->array = malloc(array_bytes); if (!t->array) { uninit(&t->t); @@ -4465,24 +4523,32 @@ void upb_inttable_uninit(upb_inttable *t) { } bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val) { - assert(upb_arrhas(val.val)); + /* XXX: Table can't store value (uint64_t)-1. Need to somehow statically + * guarantee that this is not necessary, or fix the limitation. */ + upb_tabval tabval; + tabval.val = val.val; + UPB_UNUSED(tabval); + assert(upb_arrhas(tabval)); + if (key < t->array_size) { assert(!upb_arrhas(t->array[key])); t->array_count++; - mutable_array(t)[key] = val.val; + mutable_array(t)[key].val = val.val; } else { if (isfull(&t->t)) { - // Need to resize the hash part, but we re-use the array part. + /* Need to resize the hash part, but we re-use the array part. */ + size_t i; upb_table new_table; if (!init(&new_table, t->t.ctype, t->t.size_lg2 + 1)) return false; - size_t i; for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) { const upb_tabent *e = &t->t.entries[i]; + uint32_t hash; upb_value v; - _upb_value_setval(&v, e->val, t->t.ctype); - uint32_t hash = upb_inthash(e->key.num); - insert(&new_table, intkey(e->key.num), v, hash, &inthash, &inteql); + + _upb_value_setval(&v, e->val.val, t->t.ctype); + hash = upb_inthash(e->key); + insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql); } assert(t->t.count == new_table.count); @@ -4490,23 +4556,23 @@ bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val) { uninit(&t->t); t->t = new_table; } - insert(&t->t, intkey(key), val, upb_inthash(key), &inthash, &inteql); + insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql); } check(t); return true; } bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) { - const _upb_value *table_v = inttable_val_const(t, key); + const upb_tabval *table_v = inttable_val_const(t, key); if (!table_v) return false; - if (v) _upb_value_setval(v, *table_v, t->t.ctype); + if (v) _upb_value_setval(v, table_v->val, t->t.ctype); return true; } bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val) { - _upb_value *table_v = inttable_val(t, key); + upb_tabval *table_v = inttable_val(t, key); if (!table_v) return false; - *table_v = val.val; + table_v->val = val.val; return true; } @@ -4514,11 +4580,11 @@ bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) { bool success; if (key < t->array_size) { if (upb_arrhas(t->array[key])) { + upb_tabval empty = UPB_TABVALUE_EMPTY_INIT; t->array_count--; if (val) { - _upb_value_setval(val, t->array[key], t->t.ctype); + _upb_value_setval(val, t->array[key].val, t->t.ctype); } - _upb_value empty = UPB_ARRAY_EMPTYENT; mutable_array(t)[key] = empty; success = true; } else { @@ -4558,10 +4624,14 @@ bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val) { } void upb_inttable_compact(upb_inttable *t) { - // Create a power-of-two histogram of the table keys. + /* Create a power-of-two histogram of the table keys. */ int counts[UPB_MAXARRSIZE + 1] = {0}; uintptr_t max_key = 0; upb_inttable_iter i; + size_t arr_size; + int arr_count; + upb_inttable new_t; + upb_inttable_begin(&i, t); for (; !upb_inttable_done(&i); upb_inttable_next(&i)) { uintptr_t key = upb_inttable_iter_key(&i); @@ -4571,15 +4641,17 @@ void upb_inttable_compact(upb_inttable *t) { counts[log2ceil(key)]++; } - size_t arr_size = 1; - int arr_count = upb_inttable_count(t); + arr_size = 1; + arr_count = upb_inttable_count(t); if (upb_inttable_count(t) >= max_key * MIN_DENSITY) { - // We can put 100% of the entries in the array part. + /* We can put 100% of the entries in the array part. */ arr_size = max_key + 1; } else { - // Find the largest power of two that satisfies the MIN_DENSITY definition. - for (int size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 1; size_lg2--) { + /* Find the largest power of two that satisfies the MIN_DENSITY + * definition. */ + int size_lg2; + for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 1; size_lg2--) { arr_size = 1 << size_lg2; arr_count -= counts[size_lg2]; if (arr_count >= arr_size * MIN_DENSITY) { @@ -4588,38 +4660,39 @@ void upb_inttable_compact(upb_inttable *t) { } } - // Array part must always be at least 1 entry large to catch lookups of key - // 0. Key 0 must always be in the array part because "0" in the hash part - // denotes an empty entry. + /* Array part must always be at least 1 entry large to catch lookups of key + * 0. Key 0 must always be in the array part because "0" in the hash part + * denotes an empty entry. */ arr_size = UPB_MAX(arr_size, 1); - // Insert all elements into new, perfectly-sized table. - int hash_count = upb_inttable_count(t) - arr_count; - int hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0; - int hashsize_lg2 = log2ceil(hash_size); - assert(hash_count >= 0); - - upb_inttable new_t; - upb_inttable_sizedinit(&new_t, t->t.ctype, arr_size, hashsize_lg2); - upb_inttable_begin(&i, t); - for (; !upb_inttable_done(&i); upb_inttable_next(&i)) { - uintptr_t k = upb_inttable_iter_key(&i); - upb_inttable_insert(&new_t, k, upb_inttable_iter_value(&i)); + { + /* Insert all elements into new, perfectly-sized table. */ + int hash_count = upb_inttable_count(t) - arr_count; + int hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0; + int hashsize_lg2 = log2ceil(hash_size); + + assert(hash_count >= 0); + upb_inttable_sizedinit(&new_t, t->t.ctype, arr_size, hashsize_lg2); + upb_inttable_begin(&i, t); + for (; !upb_inttable_done(&i); upb_inttable_next(&i)) { + uintptr_t k = upb_inttable_iter_key(&i); + upb_inttable_insert(&new_t, k, upb_inttable_iter_value(&i)); + } + assert(new_t.array_size == arr_size); + assert(new_t.t.size_lg2 == hashsize_lg2); } - assert(new_t.array_size == arr_size); - assert(new_t.t.size_lg2 == hashsize_lg2); upb_inttable_uninit(t); *t = new_t; } -// Iteration. +/* Iteration. */ static const upb_tabent *int_tabent(const upb_inttable_iter *i) { assert(!i->array_part); return &i->t->t.entries[i->index]; } -static _upb_value int_arrent(const upb_inttable_iter *i) { +static upb_tabval int_arrent(const upb_inttable_iter *i) { assert(i->array_part); return i->t->array[i->index]; } @@ -4658,13 +4731,13 @@ bool upb_inttable_done(const upb_inttable_iter *i) { uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) { assert(!upb_inttable_done(i)); - return i->array_part ? i->index : int_tabent(i)->key.num; + return i->array_part ? i->index : int_tabent(i)->key; } upb_value upb_inttable_iter_value(const upb_inttable_iter *i) { assert(!upb_inttable_done(i)); return _upb_value_val( - i->array_part ? i->t->array[i->index] : int_tabent(i)->val, + i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val, i->t->t.ctype); } @@ -4682,26 +4755,26 @@ bool upb_inttable_iter_isequal(const upb_inttable_iter *i1, } #ifdef UPB_UNALIGNED_READS_OK -//----------------------------------------------------------------------------- -// MurmurHash2, by Austin Appleby (released as public domain). -// Reformatted and C99-ified by Joshua Haberman. -// Note - This code makes a few assumptions about how your machine behaves - -// 1. We can read a 4-byte value from any address without crashing -// 2. sizeof(int) == 4 (in upb this limitation is removed by using uint32_t -// And it has a few limitations - -// 1. It will not work incrementally. -// 2. It will not produce the same results on little-endian and big-endian -// machines. +/* ----------------------------------------------------------------------------- + * MurmurHash2, by Austin Appleby (released as public domain). + * Reformatted and C99-ified by Joshua Haberman. + * Note - This code makes a few assumptions about how your machine behaves - + * 1. We can read a 4-byte value from any address without crashing + * 2. sizeof(int) == 4 (in upb this limitation is removed by using uint32_t + * And it has a few limitations - + * 1. It will not work incrementally. + * 2. It will not produce the same results on little-endian and big-endian + * machines. */ uint32_t MurmurHash2(const void *key, size_t len, uint32_t seed) { - // 'm' and 'r' are mixing constants generated offline. - // They're not really 'magic', they just happen to work well. + /* 'm' and 'r' are mixing constants generated offline. + * They're not really 'magic', they just happen to work well. */ const uint32_t m = 0x5bd1e995; const int32_t r = 24; - // Initialize the hash to a 'random' value + /* Initialize the hash to a 'random' value */ uint32_t h = seed ^ len; - // Mix 4 bytes at a time into the hash + /* Mix 4 bytes at a time into the hash */ const uint8_t * data = (const uint8_t *)key; while(len >= 4) { uint32_t k = *(uint32_t *)data; @@ -4717,15 +4790,15 @@ uint32_t MurmurHash2(const void *key, size_t len, uint32_t seed) { len -= 4; } - // Handle the last few bytes of the input array + /* Handle the last few bytes of the input array */ switch(len) { case 3: h ^= data[2] << 16; case 2: h ^= data[1] << 8; case 1: h ^= data[0]; h *= m; }; - // Do a few final mixes of the hash to ensure the last few - // bytes are well-incorporated. + /* Do a few final mixes of the hash to ensure the last few + * bytes are well-incorporated. */ h ^= h >> 13; h *= m; h ^= h >> 15; @@ -4733,13 +4806,13 @@ uint32_t MurmurHash2(const void *key, size_t len, uint32_t seed) { return h; } -#else // !UPB_UNALIGNED_READS_OK +#else /* !UPB_UNALIGNED_READS_OK */ -//----------------------------------------------------------------------------- -// MurmurHashAligned2, by Austin Appleby -// Same algorithm as MurmurHash2, but only does aligned reads - should be safer -// on certain platforms. -// Performance will be lower than MurmurHash2 +/* ----------------------------------------------------------------------------- + * MurmurHashAligned2, by Austin Appleby + * Same algorithm as MurmurHash2, but only does aligned reads - should be safer + * on certain platforms. + * Performance will be lower than MurmurHash2 */ #define MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; } @@ -4751,8 +4824,10 @@ uint32_t MurmurHash2(const void * key, size_t len, uint32_t seed) { uint8_t align = (uintptr_t)data & 3; if(align && (len >= 4)) { - // Pre-load the temp registers + /* Pre-load the temp registers */ uint32_t t = 0, d = 0; + int32_t sl; + int32_t sr; switch(align) { case 1: t |= data[2] << 16; @@ -4765,16 +4840,18 @@ uint32_t MurmurHash2(const void * key, size_t len, uint32_t seed) { data += 4-align; len -= 4-align; - int32_t sl = 8 * (4-align); - int32_t sr = 8 * align; + sl = 8 * (4-align); + sr = 8 * align; - // Mix + /* Mix */ while(len >= 4) { + uint32_t k; + d = *(uint32_t *)data; t = (t >> sr) | (d << sl); - uint32_t k = t; + k = t; MIX(h,k,m); @@ -4784,25 +4861,27 @@ uint32_t MurmurHash2(const void * key, size_t len, uint32_t seed) { len -= 4; } - // Handle leftover data in temp registers + /* Handle leftover data in temp registers */ d = 0; if(len >= align) { + uint32_t k; + switch(align) { case 3: d |= data[2] << 16; case 2: d |= data[1] << 8; case 1: d |= data[0]; } - uint32_t k = (t >> sr) | (d << sl); + k = (t >> sr) | (d << sl); MIX(h,k,m); data += align; len -= align; - //---------- - // Handle tail bytes + /* ---------- + * Handle tail bytes */ switch(len) { case 3: h ^= data[2] << 16; @@ -4833,8 +4912,8 @@ uint32_t MurmurHash2(const void * key, size_t len, uint32_t seed) { len -= 4; } - //---------- - // Handle tail bytes + /* ---------- + * Handle tail bytes */ switch(len) { case 3: h ^= data[2] << 16; @@ -4851,7 +4930,7 @@ uint32_t MurmurHash2(const void * key, size_t len, uint32_t seed) { } #undef MIX -#endif // UPB_UNALIGNED_READS_OK +#endif /* UPB_UNALIGNED_READS_OK */ /* * upb - a minimalist implementation of protocol buffers. * @@ -4873,10 +4952,10 @@ bool upb_dumptostderr(void *closure, const upb_status* status) { return false; } -// Guarantee null-termination and provide ellipsis truncation. -// It may be tempting to "optimize" this by initializing these final -// four bytes up-front and then being careful never to overwrite them, -// this is safer and simpler. +/* Guarantee null-termination and provide ellipsis truncation. + * It may be tempting to "optimize" this by initializing these final + * four bytes up-front and then being careful never to overwrite them, + * this is safer and simpler. */ static void nullz(upb_status *status) { const char *ellipsis = "..."; size_t len = strlen(ellipsis); @@ -4918,7 +4997,7 @@ void upb_status_seterrf(upb_status *status, const char *fmt, ...) { void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) { if (!status) return; status->ok_ = false; - vsnprintf(status->msg, sizeof(status->msg), fmt, args); + _upb_vsnprintf(status->msg, sizeof(status->msg), fmt, args); nullz(status); } @@ -4935,9 +5014,9 @@ void upb_status_copy(upb_status *to, const upb_status *from) { if (!to) return; *to = *from; } -// This file was generated by upbc (the upb compiler). -// Do not edit -- your changes will be discarded when the file is -// regenerated. +/* This file was generated by upbc (the upb compiler). + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ static const upb_msgdef msgs[20]; @@ -4945,7 +5024,7 @@ static const upb_fielddef fields[81]; static const upb_enumdef enums[4]; static const upb_tabent strentries[236]; static const upb_tabent intentries[14]; -static const _upb_value arrays[232]; +static const upb_tabval arrays[232]; #ifdef UPB_DEBUG_REFS static upb_inttable reftables[212]; @@ -4978,21 +5057,21 @@ static const upb_fielddef fields[81] = { UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "aggregate_value", 8, &msgs[18], NULL, 15, 6, {0},&reftables[40], &reftables[41]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "allow_alias", 2, &msgs[3], NULL, 6, 1, {0},&reftables[42], &reftables[43]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "cc_generic_services", 16, &msgs[10], NULL, 17, 6, {0},&reftables[44], &reftables[45]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "ctype", 1, &msgs[7], UPB_UPCAST(&enums[2]), 6, 1, {0},&reftables[46], &reftables[47]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "ctype", 1, &msgs[7], (const upb_def*)(&enums[2]), 6, 1, {0},&reftables[46], &reftables[47]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "default_value", 7, &msgs[6], NULL, 16, 7, {0},&reftables[48], &reftables[49]), UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "dependency", 3, &msgs[8], NULL, 30, 8, {0},&reftables[50], &reftables[51]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[7], NULL, 8, 3, {0},&reftables[52], &reftables[53]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, false, false, false, "double_value", 6, &msgs[18], NULL, 11, 4, {0},&reftables[54], &reftables[55]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "end", 2, &msgs[1], NULL, 3, 1, {0},&reftables[56], &reftables[57]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 4, &msgs[0], UPB_UPCAST(&msgs[2]), 16, 2, {0},&reftables[58], &reftables[59]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 5, &msgs[8], UPB_UPCAST(&msgs[2]), 13, 1, {0},&reftables[60], &reftables[61]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 4, &msgs[0], (const upb_def*)(&msgs[2]), 16, 2, {0},&reftables[58], &reftables[59]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 5, &msgs[8], (const upb_def*)(&msgs[2]), 13, 1, {0},&reftables[60], &reftables[61]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "experimental_map_key", 9, &msgs[7], NULL, 10, 5, {0},&reftables[62], &reftables[63]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "extendee", 2, &msgs[6], NULL, 7, 2, {0},&reftables[64], &reftables[65]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 7, &msgs[8], UPB_UPCAST(&msgs[6]), 19, 3, {0},&reftables[66], &reftables[67]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 6, &msgs[0], UPB_UPCAST(&msgs[6]), 22, 4, {0},&reftables[68], &reftables[69]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension_range", 5, &msgs[0], UPB_UPCAST(&msgs[1]), 19, 3, {0},&reftables[70], &reftables[71]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "field", 2, &msgs[0], UPB_UPCAST(&msgs[6]), 10, 0, {0},&reftables[72], &reftables[73]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "file", 1, &msgs[9], UPB_UPCAST(&msgs[8]), 5, 0, {0},&reftables[74], &reftables[75]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 7, &msgs[8], (const upb_def*)(&msgs[6]), 19, 3, {0},&reftables[66], &reftables[67]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 6, &msgs[0], (const upb_def*)(&msgs[6]), 22, 4, {0},&reftables[68], &reftables[69]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension_range", 5, &msgs[0], (const upb_def*)(&msgs[1]), 19, 3, {0},&reftables[70], &reftables[71]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "field", 2, &msgs[0], (const upb_def*)(&msgs[6]), 10, 0, {0},&reftables[72], &reftables[73]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "file", 1, &msgs[9], (const upb_def*)(&msgs[8]), 5, 0, {0},&reftables[74], &reftables[75]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "go_package", 11, &msgs[10], NULL, 14, 5, {0},&reftables[76], &reftables[77]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "identifier_value", 3, &msgs[18], NULL, 6, 1, {0},&reftables[78], &reftables[79]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "input_type", 2, &msgs[12], NULL, 7, 2, {0},&reftables[80], &reftables[81]), @@ -5002,16 +5081,16 @@ static const upb_fielddef fields[81] = { UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_multiple_files", 10, &msgs[10], NULL, 13, 4, {0},&reftables[88], &reftables[89]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "java_outer_classname", 8, &msgs[10], NULL, 9, 2, {0},&reftables[90], &reftables[91]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "java_package", 1, &msgs[10], NULL, 6, 1, {0},&reftables[92], &reftables[93]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "label", 4, &msgs[6], UPB_UPCAST(&enums[0]), 11, 4, {0},&reftables[94], &reftables[95]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "label", 4, &msgs[6], (const upb_def*)(&enums[0]), 11, 4, {0},&reftables[94], &reftables[95]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "lazy", 5, &msgs[7], NULL, 9, 4, {0},&reftables[96], &reftables[97]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "leading_comments", 3, &msgs[17], NULL, 8, 2, {0},&reftables[98], &reftables[99]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "location", 1, &msgs[16], UPB_UPCAST(&msgs[17]), 5, 0, {0},&reftables[100], &reftables[101]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "location", 1, &msgs[16], (const upb_def*)(&msgs[17]), 5, 0, {0},&reftables[100], &reftables[101]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "message_set_wire_format", 1, &msgs[11], NULL, 6, 1, {0},&reftables[102], &reftables[103]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "message_type", 4, &msgs[8], UPB_UPCAST(&msgs[0]), 10, 0, {0},&reftables[104], &reftables[105]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "method", 2, &msgs[14], UPB_UPCAST(&msgs[12]), 6, 0, {0},&reftables[106], &reftables[107]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "message_type", 4, &msgs[8], (const upb_def*)(&msgs[0]), 10, 0, {0},&reftables[104], &reftables[105]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "method", 2, &msgs[14], (const upb_def*)(&msgs[12]), 6, 0, {0},&reftables[106], &reftables[107]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[8], NULL, 22, 6, {0},&reftables[108], &reftables[109]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[14], NULL, 8, 2, {0},&reftables[110], &reftables[111]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "name", 2, &msgs[18], UPB_UPCAST(&msgs[19]), 5, 0, {0},&reftables[112], &reftables[113]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "name", 2, &msgs[18], (const upb_def*)(&msgs[19]), 5, 0, {0},&reftables[112], &reftables[113]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[4], NULL, 4, 1, {0},&reftables[114], &reftables[115]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[0], NULL, 24, 6, {0},&reftables[116], &reftables[117]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[12], NULL, 4, 1, {0},&reftables[118], &reftables[119]), @@ -5019,18 +5098,18 @@ static const upb_fielddef fields[81] = { UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[6], NULL, 4, 1, {0},&reftables[122], &reftables[123]), UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_STRING, 0, false, false, false, false, "name_part", 1, &msgs[19], NULL, 2, 0, {0},&reftables[124], &reftables[125]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, false, false, false, "negative_int_value", 5, &msgs[18], NULL, 10, 3, {0},&reftables[126], &reftables[127]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "nested_type", 3, &msgs[0], UPB_UPCAST(&msgs[0]), 13, 1, {0},&reftables[128], &reftables[129]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "nested_type", 3, &msgs[0], (const upb_def*)(&msgs[0]), 13, 1, {0},&reftables[128], &reftables[129]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "no_standard_descriptor_accessor", 2, &msgs[11], NULL, 7, 2, {0},&reftables[130], &reftables[131]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 3, &msgs[6], NULL, 10, 3, {0},&reftables[132], &reftables[133]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 2, &msgs[4], NULL, 7, 2, {0},&reftables[134], &reftables[135]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "optimize_for", 9, &msgs[10], UPB_UPCAST(&enums[3]), 12, 3, {0},&reftables[136], &reftables[137]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 7, &msgs[0], UPB_UPCAST(&msgs[11]), 23, 5, {0},&reftables[138], &reftables[139]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[2], UPB_UPCAST(&msgs[3]), 7, 1, {0},&reftables[140], &reftables[141]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[6], UPB_UPCAST(&msgs[7]), 3, 0, {0},&reftables[142], &reftables[143]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[4], UPB_UPCAST(&msgs[5]), 3, 0, {0},&reftables[144], &reftables[145]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[8], UPB_UPCAST(&msgs[10]), 20, 4, {0},&reftables[146], &reftables[147]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[14], UPB_UPCAST(&msgs[15]), 7, 1, {0},&reftables[148], &reftables[149]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 4, &msgs[12], UPB_UPCAST(&msgs[13]), 3, 0, {0},&reftables[150], &reftables[151]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "optimize_for", 9, &msgs[10], (const upb_def*)(&enums[3]), 12, 3, {0},&reftables[136], &reftables[137]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 7, &msgs[0], (const upb_def*)(&msgs[11]), 23, 5, {0},&reftables[138], &reftables[139]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[2], (const upb_def*)(&msgs[3]), 7, 1, {0},&reftables[140], &reftables[141]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[6], (const upb_def*)(&msgs[7]), 3, 0, {0},&reftables[142], &reftables[143]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[4], (const upb_def*)(&msgs[5]), 3, 0, {0},&reftables[144], &reftables[145]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[8], (const upb_def*)(&msgs[10]), 20, 4, {0},&reftables[146], &reftables[147]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[14], (const upb_def*)(&msgs[15]), 7, 1, {0},&reftables[148], &reftables[149]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 4, &msgs[12], (const upb_def*)(&msgs[13]), 3, 0, {0},&reftables[150], &reftables[151]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "output_type", 3, &msgs[12], NULL, 10, 3, {0},&reftables[152], &reftables[153]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "package", 2, &msgs[8], NULL, 25, 7, {0},&reftables[154], &reftables[155]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "packed", 2, &msgs[7], NULL, 7, 2, {0},&reftables[156], &reftables[157]), @@ -5038,22 +5117,22 @@ static const upb_fielddef fields[81] = { UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, false, false, false, "positive_int_value", 4, &msgs[18], NULL, 9, 2, {0},&reftables[160], &reftables[161]), UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "public_dependency", 10, &msgs[8], NULL, 35, 9, {0},&reftables[162], &reftables[163]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "py_generic_services", 18, &msgs[10], NULL, 19, 8, {0},&reftables[164], &reftables[165]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "service", 6, &msgs[8], UPB_UPCAST(&msgs[14]), 16, 2, {0},&reftables[166], &reftables[167]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "source_code_info", 9, &msgs[8], UPB_UPCAST(&msgs[16]), 21, 5, {0},&reftables[168], &reftables[169]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "service", 6, &msgs[8], (const upb_def*)(&msgs[14]), 16, 2, {0},&reftables[166], &reftables[167]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "source_code_info", 9, &msgs[8], (const upb_def*)(&msgs[16]), 21, 5, {0},&reftables[168], &reftables[169]), UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "span", 2, &msgs[17], NULL, 7, 1, {0},&reftables[170], &reftables[171]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[1], NULL, 2, 0, {0},&reftables[172], &reftables[173]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, false, false, false, "string_value", 7, &msgs[18], NULL, 12, 5, {0},&reftables[174], &reftables[175]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "trailing_comments", 4, &msgs[17], NULL, 11, 3, {0},&reftables[176], &reftables[177]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "type", 5, &msgs[6], UPB_UPCAST(&enums[1]), 12, 5, {0},&reftables[178], &reftables[179]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "type", 5, &msgs[6], (const upb_def*)(&enums[1]), 12, 5, {0},&reftables[178], &reftables[179]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "type_name", 6, &msgs[6], NULL, 13, 6, {0},&reftables[180], &reftables[181]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[5], UPB_UPCAST(&msgs[18]), 5, 0, {0},&reftables[182], &reftables[183]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[15], UPB_UPCAST(&msgs[18]), 5, 0, {0},&reftables[184], &reftables[185]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[3], UPB_UPCAST(&msgs[18]), 5, 0, {0},&reftables[186], &reftables[187]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[13], UPB_UPCAST(&msgs[18]), 5, 0, {0},&reftables[188], &reftables[189]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[10], UPB_UPCAST(&msgs[18]), 5, 0, {0},&reftables[190], &reftables[191]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[11], UPB_UPCAST(&msgs[18]), 5, 0, {0},&reftables[192], &reftables[193]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[7], UPB_UPCAST(&msgs[18]), 5, 0, {0},&reftables[194], &reftables[195]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "value", 2, &msgs[2], UPB_UPCAST(&msgs[4]), 6, 0, {0},&reftables[196], &reftables[197]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[5], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[182], &reftables[183]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[15], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[184], &reftables[185]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[3], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[186], &reftables[187]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[13], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[188], &reftables[189]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[10], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[190], &reftables[191]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[11], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[192], &reftables[193]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[7], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[194], &reftables[195]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "value", 2, &msgs[2], (const upb_def*)(&msgs[4]), 6, 0, {0},&reftables[196], &reftables[197]), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "weak", 10, &msgs[7], NULL, 13, 6, {0},&reftables[198], &reftables[199]), UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "weak_dependency", 11, &msgs[8], NULL, 38, 10, {0},&reftables[200], &reftables[201]), }; @@ -5066,494 +5145,494 @@ static const upb_enumdef enums[4] = { }; static const upb_tabent strentries[236] = { - {UPB_TABKEY_STR("extension"), UPB_VALUE_INIT_CONSTPTR(&fields[14]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&fields[38]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("field"), UPB_VALUE_INIT_CONSTPTR(&fields[16]), NULL}, - {UPB_TABKEY_STR("extension_range"), UPB_VALUE_INIT_CONSTPTR(&fields[15]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("nested_type"), UPB_VALUE_INIT_CONSTPTR(&fields[44]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&fields[49]), NULL}, - {UPB_TABKEY_STR("enum_type"), UPB_VALUE_INIT_CONSTPTR(&fields[9]), &strentries[14]}, - {UPB_TABKEY_STR("start"), UPB_VALUE_INIT_CONSTPTR(&fields[66]), NULL}, - {UPB_TABKEY_STR("end"), UPB_VALUE_INIT_CONSTPTR(&fields[8]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("value"), UPB_VALUE_INIT_CONSTPTR(&fields[78]), NULL}, - {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&fields[50]), NULL}, - {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&fields[40]), &strentries[22]}, - {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&fields[73]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("allow_alias"), UPB_VALUE_INIT_CONSTPTR(&fields[1]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("number"), UPB_VALUE_INIT_CONSTPTR(&fields[47]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&fields[52]), NULL}, - {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&fields[37]), &strentries[30]}, - {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&fields[71]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("label"), UPB_VALUE_INIT_CONSTPTR(&fields[27]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&fields[41]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("number"), UPB_VALUE_INIT_CONSTPTR(&fields[46]), &strentries[49]}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("type_name"), UPB_VALUE_INIT_CONSTPTR(&fields[70]), NULL}, - {UPB_TABKEY_STR("extendee"), UPB_VALUE_INIT_CONSTPTR(&fields[12]), NULL}, - {UPB_TABKEY_STR("type"), UPB_VALUE_INIT_CONSTPTR(&fields[69]), &strentries[48]}, - {UPB_TABKEY_STR("default_value"), UPB_VALUE_INIT_CONSTPTR(&fields[4]), NULL}, - {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&fields[51]), NULL}, - {UPB_TABKEY_STR("experimental_map_key"), UPB_VALUE_INIT_CONSTPTR(&fields[11]), &strentries[67]}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("weak"), UPB_VALUE_INIT_CONSTPTR(&fields[79]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("packed"), UPB_VALUE_INIT_CONSTPTR(&fields[58]), NULL}, - {UPB_TABKEY_STR("lazy"), UPB_VALUE_INIT_CONSTPTR(&fields[28]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("ctype"), UPB_VALUE_INIT_CONSTPTR(&fields[3]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("deprecated"), UPB_VALUE_INIT_CONSTPTR(&fields[6]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&fields[77]), NULL}, - {UPB_TABKEY_STR("extension"), UPB_VALUE_INIT_CONSTPTR(&fields[13]), NULL}, - {UPB_TABKEY_STR("weak_dependency"), UPB_VALUE_INIT_CONSTPTR(&fields[80]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&fields[34]), NULL}, - {UPB_TABKEY_STR("service"), UPB_VALUE_INIT_CONSTPTR(&fields[63]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("source_code_info"), UPB_VALUE_INIT_CONSTPTR(&fields[64]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("dependency"), UPB_VALUE_INIT_CONSTPTR(&fields[5]), NULL}, - {UPB_TABKEY_STR("message_type"), UPB_VALUE_INIT_CONSTPTR(&fields[32]), NULL}, - {UPB_TABKEY_STR("package"), UPB_VALUE_INIT_CONSTPTR(&fields[57]), NULL}, - {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&fields[53]), &strentries[82]}, - {UPB_TABKEY_STR("enum_type"), UPB_VALUE_INIT_CONSTPTR(&fields[10]), NULL}, - {UPB_TABKEY_STR("public_dependency"), UPB_VALUE_INIT_CONSTPTR(&fields[61]), &strentries[81]}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("file"), UPB_VALUE_INIT_CONSTPTR(&fields[17]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&fields[75]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("cc_generic_services"), UPB_VALUE_INIT_CONSTPTR(&fields[2]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("java_multiple_files"), UPB_VALUE_INIT_CONSTPTR(&fields[24]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("java_generic_services"), UPB_VALUE_INIT_CONSTPTR(&fields[23]), &strentries[102]}, - {UPB_TABKEY_STR("java_generate_equals_and_hash"), UPB_VALUE_INIT_CONSTPTR(&fields[22]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("go_package"), UPB_VALUE_INIT_CONSTPTR(&fields[18]), NULL}, - {UPB_TABKEY_STR("java_package"), UPB_VALUE_INIT_CONSTPTR(&fields[26]), NULL}, - {UPB_TABKEY_STR("optimize_for"), UPB_VALUE_INIT_CONSTPTR(&fields[48]), NULL}, - {UPB_TABKEY_STR("py_generic_services"), UPB_VALUE_INIT_CONSTPTR(&fields[62]), NULL}, - {UPB_TABKEY_STR("java_outer_classname"), UPB_VALUE_INIT_CONSTPTR(&fields[25]), NULL}, - {UPB_TABKEY_STR("message_set_wire_format"), UPB_VALUE_INIT_CONSTPTR(&fields[31]), &strentries[106]}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&fields[76]), NULL}, - {UPB_TABKEY_STR("no_standard_descriptor_accessor"), UPB_VALUE_INIT_CONSTPTR(&fields[45]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&fields[39]), NULL}, - {UPB_TABKEY_STR("input_type"), UPB_VALUE_INIT_CONSTPTR(&fields[20]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("output_type"), UPB_VALUE_INIT_CONSTPTR(&fields[56]), NULL}, - {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&fields[55]), NULL}, - {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&fields[74]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&fields[54]), &strentries[122]}, - {UPB_TABKEY_STR("method"), UPB_VALUE_INIT_CONSTPTR(&fields[33]), NULL}, - {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&fields[35]), &strentries[121]}, - {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&fields[72]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("location"), UPB_VALUE_INIT_CONSTPTR(&fields[30]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("span"), UPB_VALUE_INIT_CONSTPTR(&fields[65]), &strentries[139]}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("trailing_comments"), UPB_VALUE_INIT_CONSTPTR(&fields[68]), NULL}, - {UPB_TABKEY_STR("leading_comments"), UPB_VALUE_INIT_CONSTPTR(&fields[29]), &strentries[137]}, - {UPB_TABKEY_STR("path"), UPB_VALUE_INIT_CONSTPTR(&fields[59]), NULL}, - {UPB_TABKEY_STR("double_value"), UPB_VALUE_INIT_CONSTPTR(&fields[7]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&fields[36]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("negative_int_value"), UPB_VALUE_INIT_CONSTPTR(&fields[43]), NULL}, - {UPB_TABKEY_STR("aggregate_value"), UPB_VALUE_INIT_CONSTPTR(&fields[0]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("positive_int_value"), UPB_VALUE_INIT_CONSTPTR(&fields[60]), NULL}, - {UPB_TABKEY_STR("identifier_value"), UPB_VALUE_INIT_CONSTPTR(&fields[19]), NULL}, - {UPB_TABKEY_STR("string_value"), UPB_VALUE_INIT_CONSTPTR(&fields[67]), &strentries[154]}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("is_extension"), UPB_VALUE_INIT_CONSTPTR(&fields[21]), NULL}, - {UPB_TABKEY_STR("name_part"), UPB_VALUE_INIT_CONSTPTR(&fields[42]), NULL}, - {UPB_TABKEY_STR("LABEL_REQUIRED"), UPB_VALUE_INIT_INT32(2), &strentries[162]}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("LABEL_REPEATED"), UPB_VALUE_INIT_INT32(3), NULL}, - {UPB_TABKEY_STR("LABEL_OPTIONAL"), UPB_VALUE_INIT_INT32(1), NULL}, - {UPB_TABKEY_STR("TYPE_FIXED64"), UPB_VALUE_INIT_INT32(6), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("TYPE_STRING"), UPB_VALUE_INIT_INT32(9), NULL}, - {UPB_TABKEY_STR("TYPE_FLOAT"), UPB_VALUE_INIT_INT32(2), &strentries[193]}, - {UPB_TABKEY_STR("TYPE_DOUBLE"), UPB_VALUE_INIT_INT32(1), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("TYPE_INT32"), UPB_VALUE_INIT_INT32(5), NULL}, - {UPB_TABKEY_STR("TYPE_SFIXED32"), UPB_VALUE_INIT_INT32(15), NULL}, - {UPB_TABKEY_STR("TYPE_FIXED32"), UPB_VALUE_INIT_INT32(7), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("TYPE_MESSAGE"), UPB_VALUE_INIT_INT32(11), &strentries[194]}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("TYPE_INT64"), UPB_VALUE_INIT_INT32(3), &strentries[191]}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("TYPE_ENUM"), UPB_VALUE_INIT_INT32(14), NULL}, - {UPB_TABKEY_STR("TYPE_UINT32"), UPB_VALUE_INIT_INT32(13), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("TYPE_UINT64"), UPB_VALUE_INIT_INT32(4), &strentries[190]}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("TYPE_SFIXED64"), UPB_VALUE_INIT_INT32(16), NULL}, - {UPB_TABKEY_STR("TYPE_BYTES"), UPB_VALUE_INIT_INT32(12), NULL}, - {UPB_TABKEY_STR("TYPE_SINT64"), UPB_VALUE_INIT_INT32(18), NULL}, - {UPB_TABKEY_STR("TYPE_BOOL"), UPB_VALUE_INIT_INT32(8), NULL}, - {UPB_TABKEY_STR("TYPE_GROUP"), UPB_VALUE_INIT_INT32(10), NULL}, - {UPB_TABKEY_STR("TYPE_SINT32"), UPB_VALUE_INIT_INT32(17), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("CORD"), UPB_VALUE_INIT_INT32(1), NULL}, - {UPB_TABKEY_STR("STRING"), UPB_VALUE_INIT_INT32(0), &strentries[197]}, - {UPB_TABKEY_STR("STRING_PIECE"), UPB_VALUE_INIT_INT32(2), NULL}, - {UPB_TABKEY_STR("CODE_SIZE"), UPB_VALUE_INIT_INT32(2), NULL}, - {UPB_TABKEY_STR("SPEED"), UPB_VALUE_INIT_INT32(1), &strentries[203]}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("LITE_RUNTIME"), UPB_VALUE_INIT_INT32(3), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("google.protobuf.SourceCodeInfo.Location"), UPB_VALUE_INIT_CONSTPTR(&msgs[17]), NULL}, - {UPB_TABKEY_STR("google.protobuf.UninterpretedOption"), UPB_VALUE_INIT_CONSTPTR(&msgs[18]), NULL}, - {UPB_TABKEY_STR("google.protobuf.FileDescriptorProto"), UPB_VALUE_INIT_CONSTPTR(&msgs[8]), NULL}, - {UPB_TABKEY_STR("google.protobuf.MethodDescriptorProto"), UPB_VALUE_INIT_CONSTPTR(&msgs[12]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("google.protobuf.EnumValueOptions"), UPB_VALUE_INIT_CONSTPTR(&msgs[5]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("google.protobuf.DescriptorProto"), UPB_VALUE_INIT_CONSTPTR(&msgs[0]), &strentries[228]}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("google.protobuf.SourceCodeInfo"), UPB_VALUE_INIT_CONSTPTR(&msgs[16]), NULL}, - {UPB_TABKEY_STR("google.protobuf.FieldDescriptorProto.Type"), UPB_VALUE_INIT_CONSTPTR(&enums[1]), NULL}, - {UPB_TABKEY_STR("google.protobuf.DescriptorProto.ExtensionRange"), UPB_VALUE_INIT_CONSTPTR(&msgs[1]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("google.protobuf.EnumValueDescriptorProto"), UPB_VALUE_INIT_CONSTPTR(&msgs[4]), NULL}, - {UPB_TABKEY_STR("google.protobuf.FieldOptions"), UPB_VALUE_INIT_CONSTPTR(&msgs[7]), NULL}, - {UPB_TABKEY_STR("google.protobuf.FileOptions"), UPB_VALUE_INIT_CONSTPTR(&msgs[10]), NULL}, - {UPB_TABKEY_STR("google.protobuf.EnumDescriptorProto"), UPB_VALUE_INIT_CONSTPTR(&msgs[2]), &strentries[233]}, - {UPB_TABKEY_STR("google.protobuf.FieldDescriptorProto.Label"), UPB_VALUE_INIT_CONSTPTR(&enums[0]), NULL}, - {UPB_TABKEY_STR("google.protobuf.ServiceDescriptorProto"), UPB_VALUE_INIT_CONSTPTR(&msgs[14]), NULL}, - {UPB_TABKEY_STR("google.protobuf.FieldOptions.CType"), UPB_VALUE_INIT_CONSTPTR(&enums[2]), &strentries[229]}, - {UPB_TABKEY_STR("google.protobuf.FileDescriptorSet"), UPB_VALUE_INIT_CONSTPTR(&msgs[9]), &strentries[235]}, - {UPB_TABKEY_STR("google.protobuf.EnumOptions"), UPB_VALUE_INIT_CONSTPTR(&msgs[3]), NULL}, - {UPB_TABKEY_STR("google.protobuf.FieldDescriptorProto"), UPB_VALUE_INIT_CONSTPTR(&msgs[6]), NULL}, - {UPB_TABKEY_STR("google.protobuf.FileOptions.OptimizeMode"), UPB_VALUE_INIT_CONSTPTR(&enums[3]), &strentries[221]}, - {UPB_TABKEY_STR("google.protobuf.ServiceOptions"), UPB_VALUE_INIT_CONSTPTR(&msgs[15]), NULL}, - {UPB_TABKEY_STR("google.protobuf.MessageOptions"), UPB_VALUE_INIT_CONSTPTR(&msgs[11]), NULL}, - {UPB_TABKEY_STR("google.protobuf.MethodOptions"), UPB_VALUE_INIT_CONSTPTR(&msgs[13]), &strentries[226]}, - {UPB_TABKEY_STR("google.protobuf.UninterpretedOption.NamePart"), UPB_VALUE_INIT_CONSTPTR(&msgs[19]), NULL}, + {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[14]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[38]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "field"), UPB_TABVALUE_PTR_INIT(&fields[16]), NULL}, + {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "extension_range"), UPB_TABVALUE_PTR_INIT(&fields[15]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "nested_type"), UPB_TABVALUE_PTR_INIT(&fields[44]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[49]), NULL}, + {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[9]), &strentries[14]}, + {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[66]), NULL}, + {UPB_TABKEY_STR("\003", "\000", "\000", "\000", "end"), UPB_TABVALUE_PTR_INIT(&fields[8]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "value"), UPB_TABVALUE_PTR_INIT(&fields[78]), NULL}, + {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[50]), NULL}, + {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[40]), &strentries[22]}, + {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[73]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "allow_alias"), UPB_TABVALUE_PTR_INIT(&fields[1]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[47]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[52]), NULL}, + {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[37]), &strentries[30]}, + {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[71]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "label"), UPB_TABVALUE_PTR_INIT(&fields[27]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[41]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[46]), &strentries[49]}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "type_name"), UPB_TABVALUE_PTR_INIT(&fields[70]), NULL}, + {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "extendee"), UPB_TABVALUE_PTR_INIT(&fields[12]), NULL}, + {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "type"), UPB_TABVALUE_PTR_INIT(&fields[69]), &strentries[48]}, + {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "default_value"), UPB_TABVALUE_PTR_INIT(&fields[4]), NULL}, + {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[51]), NULL}, + {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "experimental_map_key"), UPB_TABVALUE_PTR_INIT(&fields[11]), &strentries[67]}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "weak"), UPB_TABVALUE_PTR_INIT(&fields[79]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "packed"), UPB_TABVALUE_PTR_INIT(&fields[58]), NULL}, + {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "lazy"), UPB_TABVALUE_PTR_INIT(&fields[28]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "ctype"), UPB_TABVALUE_PTR_INIT(&fields[3]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[6]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[77]), NULL}, + {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[13]), NULL}, + {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "weak_dependency"), UPB_TABVALUE_PTR_INIT(&fields[80]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[34]), NULL}, + {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "service"), UPB_TABVALUE_PTR_INIT(&fields[63]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "source_code_info"), UPB_TABVALUE_PTR_INIT(&fields[64]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "dependency"), UPB_TABVALUE_PTR_INIT(&fields[5]), NULL}, + {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "message_type"), UPB_TABVALUE_PTR_INIT(&fields[32]), NULL}, + {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "package"), UPB_TABVALUE_PTR_INIT(&fields[57]), NULL}, + {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[53]), &strentries[82]}, + {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[10]), NULL}, + {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "public_dependency"), UPB_TABVALUE_PTR_INIT(&fields[61]), &strentries[81]}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "file"), UPB_TABVALUE_PTR_INIT(&fields[17]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[75]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "cc_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[2]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "java_multiple_files"), UPB_TABVALUE_PTR_INIT(&fields[24]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\025", "\000", "\000", "\000", "java_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[23]), &strentries[102]}, + {UPB_TABKEY_STR("\035", "\000", "\000", "\000", "java_generate_equals_and_hash"), UPB_TABVALUE_PTR_INIT(&fields[22]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "go_package"), UPB_TABVALUE_PTR_INIT(&fields[18]), NULL}, + {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "java_package"), UPB_TABVALUE_PTR_INIT(&fields[26]), NULL}, + {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "optimize_for"), UPB_TABVALUE_PTR_INIT(&fields[48]), NULL}, + {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "py_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[62]), NULL}, + {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "java_outer_classname"), UPB_TABVALUE_PTR_INIT(&fields[25]), NULL}, + {UPB_TABKEY_STR("\027", "\000", "\000", "\000", "message_set_wire_format"), UPB_TABVALUE_PTR_INIT(&fields[31]), &strentries[106]}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[76]), NULL}, + {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "no_standard_descriptor_accessor"), UPB_TABVALUE_PTR_INIT(&fields[45]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[39]), NULL}, + {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "input_type"), UPB_TABVALUE_PTR_INIT(&fields[20]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "output_type"), UPB_TABVALUE_PTR_INIT(&fields[56]), NULL}, + {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[55]), NULL}, + {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[74]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[54]), &strentries[122]}, + {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "method"), UPB_TABVALUE_PTR_INIT(&fields[33]), NULL}, + {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[35]), &strentries[121]}, + {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[72]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "location"), UPB_TABVALUE_PTR_INIT(&fields[30]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "span"), UPB_TABVALUE_PTR_INIT(&fields[65]), &strentries[139]}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "trailing_comments"), UPB_TABVALUE_PTR_INIT(&fields[68]), NULL}, + {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "leading_comments"), UPB_TABVALUE_PTR_INIT(&fields[29]), &strentries[137]}, + {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "path"), UPB_TABVALUE_PTR_INIT(&fields[59]), NULL}, + {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "double_value"), UPB_TABVALUE_PTR_INIT(&fields[7]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[36]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "negative_int_value"), UPB_TABVALUE_PTR_INIT(&fields[43]), NULL}, + {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "aggregate_value"), UPB_TABVALUE_PTR_INIT(&fields[0]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "positive_int_value"), UPB_TABVALUE_PTR_INIT(&fields[60]), NULL}, + {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "identifier_value"), UPB_TABVALUE_PTR_INIT(&fields[19]), NULL}, + {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "string_value"), UPB_TABVALUE_PTR_INIT(&fields[67]), &strentries[154]}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "is_extension"), UPB_TABVALUE_PTR_INIT(&fields[21]), NULL}, + {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "name_part"), UPB_TABVALUE_PTR_INIT(&fields[42]), NULL}, + {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_REQUIRED"), UPB_TABVALUE_INT_INIT(2), &strentries[162]}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_REPEATED"), UPB_TABVALUE_INT_INIT(3), NULL}, + {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_OPTIONAL"), UPB_TABVALUE_INT_INIT(1), NULL}, + {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_FIXED64"), UPB_TABVALUE_INT_INIT(6), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_STRING"), UPB_TABVALUE_INT_INIT(9), NULL}, + {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_FLOAT"), UPB_TABVALUE_INT_INIT(2), &strentries[193]}, + {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_DOUBLE"), UPB_TABVALUE_INT_INIT(1), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_INT32"), UPB_TABVALUE_INT_INIT(5), NULL}, + {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "TYPE_SFIXED32"), UPB_TABVALUE_INT_INIT(15), NULL}, + {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_FIXED32"), UPB_TABVALUE_INT_INIT(7), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_MESSAGE"), UPB_TABVALUE_INT_INIT(11), &strentries[194]}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_INT64"), UPB_TABVALUE_INT_INIT(3), &strentries[191]}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "TYPE_ENUM"), UPB_TABVALUE_INT_INIT(14), NULL}, + {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_UINT32"), UPB_TABVALUE_INT_INIT(13), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_UINT64"), UPB_TABVALUE_INT_INIT(4), &strentries[190]}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "TYPE_SFIXED64"), UPB_TABVALUE_INT_INIT(16), NULL}, + {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_BYTES"), UPB_TABVALUE_INT_INIT(12), NULL}, + {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_SINT64"), UPB_TABVALUE_INT_INIT(18), NULL}, + {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "TYPE_BOOL"), UPB_TABVALUE_INT_INIT(8), NULL}, + {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_GROUP"), UPB_TABVALUE_INT_INIT(10), NULL}, + {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_SINT32"), UPB_TABVALUE_INT_INIT(17), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "CORD"), UPB_TABVALUE_INT_INIT(1), NULL}, + {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "STRING"), UPB_TABVALUE_INT_INIT(0), &strentries[197]}, + {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "STRING_PIECE"), UPB_TABVALUE_INT_INIT(2), NULL}, + {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "CODE_SIZE"), UPB_TABVALUE_INT_INIT(2), NULL}, + {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "SPEED"), UPB_TABVALUE_INT_INIT(1), &strentries[203]}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "LITE_RUNTIME"), UPB_TABVALUE_INT_INIT(3), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\047", "\000", "\000", "\000", "google.protobuf.SourceCodeInfo.Location"), UPB_TABVALUE_PTR_INIT(&msgs[17]), NULL}, + {UPB_TABKEY_STR("\043", "\000", "\000", "\000", "google.protobuf.UninterpretedOption"), UPB_TABVALUE_PTR_INIT(&msgs[18]), NULL}, + {UPB_TABKEY_STR("\043", "\000", "\000", "\000", "google.protobuf.FileDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[8]), NULL}, + {UPB_TABKEY_STR("\045", "\000", "\000", "\000", "google.protobuf.MethodDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[12]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\040", "\000", "\000", "\000", "google.protobuf.EnumValueOptions"), UPB_TABVALUE_PTR_INIT(&msgs[5]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "google.protobuf.DescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[0]), &strentries[228]}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\036", "\000", "\000", "\000", "google.protobuf.SourceCodeInfo"), UPB_TABVALUE_PTR_INIT(&msgs[16]), NULL}, + {UPB_TABKEY_STR("\051", "\000", "\000", "\000", "google.protobuf.FieldDescriptorProto.Type"), UPB_TABVALUE_PTR_INIT(&enums[1]), NULL}, + {UPB_TABKEY_STR("\056", "\000", "\000", "\000", "google.protobuf.DescriptorProto.ExtensionRange"), UPB_TABVALUE_PTR_INIT(&msgs[1]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_STR("\050", "\000", "\000", "\000", "google.protobuf.EnumValueDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[4]), NULL}, + {UPB_TABKEY_STR("\034", "\000", "\000", "\000", "google.protobuf.FieldOptions"), UPB_TABVALUE_PTR_INIT(&msgs[7]), NULL}, + {UPB_TABKEY_STR("\033", "\000", "\000", "\000", "google.protobuf.FileOptions"), UPB_TABVALUE_PTR_INIT(&msgs[10]), NULL}, + {UPB_TABKEY_STR("\043", "\000", "\000", "\000", "google.protobuf.EnumDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[2]), &strentries[233]}, + {UPB_TABKEY_STR("\052", "\000", "\000", "\000", "google.protobuf.FieldDescriptorProto.Label"), UPB_TABVALUE_PTR_INIT(&enums[0]), NULL}, + {UPB_TABKEY_STR("\046", "\000", "\000", "\000", "google.protobuf.ServiceDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[14]), NULL}, + {UPB_TABKEY_STR("\042", "\000", "\000", "\000", "google.protobuf.FieldOptions.CType"), UPB_TABVALUE_PTR_INIT(&enums[2]), &strentries[229]}, + {UPB_TABKEY_STR("\041", "\000", "\000", "\000", "google.protobuf.FileDescriptorSet"), UPB_TABVALUE_PTR_INIT(&msgs[9]), &strentries[235]}, + {UPB_TABKEY_STR("\033", "\000", "\000", "\000", "google.protobuf.EnumOptions"), UPB_TABVALUE_PTR_INIT(&msgs[3]), NULL}, + {UPB_TABKEY_STR("\044", "\000", "\000", "\000", "google.protobuf.FieldDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[6]), NULL}, + {UPB_TABKEY_STR("\050", "\000", "\000", "\000", "google.protobuf.FileOptions.OptimizeMode"), UPB_TABVALUE_PTR_INIT(&enums[3]), &strentries[221]}, + {UPB_TABKEY_STR("\036", "\000", "\000", "\000", "google.protobuf.ServiceOptions"), UPB_TABVALUE_PTR_INIT(&msgs[15]), NULL}, + {UPB_TABKEY_STR("\036", "\000", "\000", "\000", "google.protobuf.MessageOptions"), UPB_TABVALUE_PTR_INIT(&msgs[11]), NULL}, + {UPB_TABKEY_STR("\035", "\000", "\000", "\000", "google.protobuf.MethodOptions"), UPB_TABVALUE_PTR_INIT(&msgs[13]), &strentries[226]}, + {UPB_TABKEY_STR("\054", "\000", "\000", "\000", "google.protobuf.UninterpretedOption.NamePart"), UPB_TABVALUE_PTR_INIT(&msgs[19]), NULL}, }; static const upb_tabent intentries[14] = { - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&fields[73]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&fields[71]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&fields[77]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&fields[75]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&fields[76]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&fields[74]), NULL}, - {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&fields[72]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[73]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[71]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[77]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[75]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[76]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[74]), NULL}, + {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, + {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[72]), NULL}, }; -static const _upb_value arrays[232] = { - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[38]), - UPB_VALUE_INIT_CONSTPTR(&fields[16]), - UPB_VALUE_INIT_CONSTPTR(&fields[44]), - UPB_VALUE_INIT_CONSTPTR(&fields[9]), - UPB_VALUE_INIT_CONSTPTR(&fields[15]), - UPB_VALUE_INIT_CONSTPTR(&fields[14]), - UPB_VALUE_INIT_CONSTPTR(&fields[49]), - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[66]), - UPB_VALUE_INIT_CONSTPTR(&fields[8]), - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[40]), - UPB_VALUE_INIT_CONSTPTR(&fields[78]), - UPB_VALUE_INIT_CONSTPTR(&fields[50]), - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[1]), - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[37]), - UPB_VALUE_INIT_CONSTPTR(&fields[47]), - UPB_VALUE_INIT_CONSTPTR(&fields[52]), - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[41]), - UPB_VALUE_INIT_CONSTPTR(&fields[12]), - UPB_VALUE_INIT_CONSTPTR(&fields[46]), - UPB_VALUE_INIT_CONSTPTR(&fields[27]), - UPB_VALUE_INIT_CONSTPTR(&fields[69]), - UPB_VALUE_INIT_CONSTPTR(&fields[70]), - UPB_VALUE_INIT_CONSTPTR(&fields[4]), - UPB_VALUE_INIT_CONSTPTR(&fields[51]), - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[3]), - UPB_VALUE_INIT_CONSTPTR(&fields[58]), - UPB_VALUE_INIT_CONSTPTR(&fields[6]), - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[28]), - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[11]), - UPB_VALUE_INIT_CONSTPTR(&fields[79]), - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[34]), - UPB_VALUE_INIT_CONSTPTR(&fields[57]), - UPB_VALUE_INIT_CONSTPTR(&fields[5]), - UPB_VALUE_INIT_CONSTPTR(&fields[32]), - UPB_VALUE_INIT_CONSTPTR(&fields[10]), - UPB_VALUE_INIT_CONSTPTR(&fields[63]), - UPB_VALUE_INIT_CONSTPTR(&fields[13]), - UPB_VALUE_INIT_CONSTPTR(&fields[53]), - UPB_VALUE_INIT_CONSTPTR(&fields[64]), - UPB_VALUE_INIT_CONSTPTR(&fields[61]), - UPB_VALUE_INIT_CONSTPTR(&fields[80]), - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[17]), - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[26]), - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[25]), - UPB_VALUE_INIT_CONSTPTR(&fields[48]), - UPB_VALUE_INIT_CONSTPTR(&fields[24]), - UPB_VALUE_INIT_CONSTPTR(&fields[18]), - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[2]), - UPB_VALUE_INIT_CONSTPTR(&fields[23]), - UPB_VALUE_INIT_CONSTPTR(&fields[62]), - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[22]), - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[31]), - UPB_VALUE_INIT_CONSTPTR(&fields[45]), - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[39]), - UPB_VALUE_INIT_CONSTPTR(&fields[20]), - UPB_VALUE_INIT_CONSTPTR(&fields[56]), - UPB_VALUE_INIT_CONSTPTR(&fields[55]), - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[35]), - UPB_VALUE_INIT_CONSTPTR(&fields[33]), - UPB_VALUE_INIT_CONSTPTR(&fields[54]), - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[30]), - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[59]), - UPB_VALUE_INIT_CONSTPTR(&fields[65]), - UPB_VALUE_INIT_CONSTPTR(&fields[29]), - UPB_VALUE_INIT_CONSTPTR(&fields[68]), - UPB_ARRAY_EMPTYENT, - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[36]), - UPB_VALUE_INIT_CONSTPTR(&fields[19]), - UPB_VALUE_INIT_CONSTPTR(&fields[60]), - UPB_VALUE_INIT_CONSTPTR(&fields[43]), - UPB_VALUE_INIT_CONSTPTR(&fields[7]), - UPB_VALUE_INIT_CONSTPTR(&fields[67]), - UPB_VALUE_INIT_CONSTPTR(&fields[0]), - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&fields[42]), - UPB_VALUE_INIT_CONSTPTR(&fields[21]), - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR("LABEL_OPTIONAL"), - UPB_VALUE_INIT_CONSTPTR("LABEL_REQUIRED"), - UPB_VALUE_INIT_CONSTPTR("LABEL_REPEATED"), - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR("TYPE_DOUBLE"), - UPB_VALUE_INIT_CONSTPTR("TYPE_FLOAT"), - UPB_VALUE_INIT_CONSTPTR("TYPE_INT64"), - UPB_VALUE_INIT_CONSTPTR("TYPE_UINT64"), - UPB_VALUE_INIT_CONSTPTR("TYPE_INT32"), - UPB_VALUE_INIT_CONSTPTR("TYPE_FIXED64"), - UPB_VALUE_INIT_CONSTPTR("TYPE_FIXED32"), - UPB_VALUE_INIT_CONSTPTR("TYPE_BOOL"), - UPB_VALUE_INIT_CONSTPTR("TYPE_STRING"), - UPB_VALUE_INIT_CONSTPTR("TYPE_GROUP"), - UPB_VALUE_INIT_CONSTPTR("TYPE_MESSAGE"), - UPB_VALUE_INIT_CONSTPTR("TYPE_BYTES"), - UPB_VALUE_INIT_CONSTPTR("TYPE_UINT32"), - UPB_VALUE_INIT_CONSTPTR("TYPE_ENUM"), - UPB_VALUE_INIT_CONSTPTR("TYPE_SFIXED32"), - UPB_VALUE_INIT_CONSTPTR("TYPE_SFIXED64"), - UPB_VALUE_INIT_CONSTPTR("TYPE_SINT32"), - UPB_VALUE_INIT_CONSTPTR("TYPE_SINT64"), - UPB_VALUE_INIT_CONSTPTR("STRING"), - UPB_VALUE_INIT_CONSTPTR("CORD"), - UPB_VALUE_INIT_CONSTPTR("STRING_PIECE"), - UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR("SPEED"), - UPB_VALUE_INIT_CONSTPTR("CODE_SIZE"), - UPB_VALUE_INIT_CONSTPTR("LITE_RUNTIME"), +static const upb_tabval arrays[232] = { + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[38]), + UPB_TABVALUE_PTR_INIT(&fields[16]), + UPB_TABVALUE_PTR_INIT(&fields[44]), + UPB_TABVALUE_PTR_INIT(&fields[9]), + UPB_TABVALUE_PTR_INIT(&fields[15]), + UPB_TABVALUE_PTR_INIT(&fields[14]), + UPB_TABVALUE_PTR_INIT(&fields[49]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[66]), + UPB_TABVALUE_PTR_INIT(&fields[8]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[40]), + UPB_TABVALUE_PTR_INIT(&fields[78]), + UPB_TABVALUE_PTR_INIT(&fields[50]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[1]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[37]), + UPB_TABVALUE_PTR_INIT(&fields[47]), + UPB_TABVALUE_PTR_INIT(&fields[52]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[41]), + UPB_TABVALUE_PTR_INIT(&fields[12]), + UPB_TABVALUE_PTR_INIT(&fields[46]), + UPB_TABVALUE_PTR_INIT(&fields[27]), + UPB_TABVALUE_PTR_INIT(&fields[69]), + UPB_TABVALUE_PTR_INIT(&fields[70]), + UPB_TABVALUE_PTR_INIT(&fields[4]), + UPB_TABVALUE_PTR_INIT(&fields[51]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[3]), + UPB_TABVALUE_PTR_INIT(&fields[58]), + UPB_TABVALUE_PTR_INIT(&fields[6]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[28]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[11]), + UPB_TABVALUE_PTR_INIT(&fields[79]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[34]), + UPB_TABVALUE_PTR_INIT(&fields[57]), + UPB_TABVALUE_PTR_INIT(&fields[5]), + UPB_TABVALUE_PTR_INIT(&fields[32]), + UPB_TABVALUE_PTR_INIT(&fields[10]), + UPB_TABVALUE_PTR_INIT(&fields[63]), + UPB_TABVALUE_PTR_INIT(&fields[13]), + UPB_TABVALUE_PTR_INIT(&fields[53]), + UPB_TABVALUE_PTR_INIT(&fields[64]), + UPB_TABVALUE_PTR_INIT(&fields[61]), + UPB_TABVALUE_PTR_INIT(&fields[80]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[17]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[26]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[25]), + UPB_TABVALUE_PTR_INIT(&fields[48]), + UPB_TABVALUE_PTR_INIT(&fields[24]), + UPB_TABVALUE_PTR_INIT(&fields[18]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[2]), + UPB_TABVALUE_PTR_INIT(&fields[23]), + UPB_TABVALUE_PTR_INIT(&fields[62]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[22]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[31]), + UPB_TABVALUE_PTR_INIT(&fields[45]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[39]), + UPB_TABVALUE_PTR_INIT(&fields[20]), + UPB_TABVALUE_PTR_INIT(&fields[56]), + UPB_TABVALUE_PTR_INIT(&fields[55]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[35]), + UPB_TABVALUE_PTR_INIT(&fields[33]), + UPB_TABVALUE_PTR_INIT(&fields[54]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[30]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[59]), + UPB_TABVALUE_PTR_INIT(&fields[65]), + UPB_TABVALUE_PTR_INIT(&fields[29]), + UPB_TABVALUE_PTR_INIT(&fields[68]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[36]), + UPB_TABVALUE_PTR_INIT(&fields[19]), + UPB_TABVALUE_PTR_INIT(&fields[60]), + UPB_TABVALUE_PTR_INIT(&fields[43]), + UPB_TABVALUE_PTR_INIT(&fields[7]), + UPB_TABVALUE_PTR_INIT(&fields[67]), + UPB_TABVALUE_PTR_INIT(&fields[0]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT(&fields[42]), + UPB_TABVALUE_PTR_INIT(&fields[21]), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT("LABEL_OPTIONAL"), + UPB_TABVALUE_PTR_INIT("LABEL_REQUIRED"), + UPB_TABVALUE_PTR_INIT("LABEL_REPEATED"), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT("TYPE_DOUBLE"), + UPB_TABVALUE_PTR_INIT("TYPE_FLOAT"), + UPB_TABVALUE_PTR_INIT("TYPE_INT64"), + UPB_TABVALUE_PTR_INIT("TYPE_UINT64"), + UPB_TABVALUE_PTR_INIT("TYPE_INT32"), + UPB_TABVALUE_PTR_INIT("TYPE_FIXED64"), + UPB_TABVALUE_PTR_INIT("TYPE_FIXED32"), + UPB_TABVALUE_PTR_INIT("TYPE_BOOL"), + UPB_TABVALUE_PTR_INIT("TYPE_STRING"), + UPB_TABVALUE_PTR_INIT("TYPE_GROUP"), + UPB_TABVALUE_PTR_INIT("TYPE_MESSAGE"), + UPB_TABVALUE_PTR_INIT("TYPE_BYTES"), + UPB_TABVALUE_PTR_INIT("TYPE_UINT32"), + UPB_TABVALUE_PTR_INIT("TYPE_ENUM"), + UPB_TABVALUE_PTR_INIT("TYPE_SFIXED32"), + UPB_TABVALUE_PTR_INIT("TYPE_SFIXED64"), + UPB_TABVALUE_PTR_INIT("TYPE_SINT32"), + UPB_TABVALUE_PTR_INIT("TYPE_SINT64"), + UPB_TABVALUE_PTR_INIT("STRING"), + UPB_TABVALUE_PTR_INIT("CORD"), + UPB_TABVALUE_PTR_INIT("STRING_PIECE"), + UPB_TABVALUE_EMPTY_INIT, + UPB_TABVALUE_PTR_INIT("SPEED"), + UPB_TABVALUE_PTR_INIT("CODE_SIZE"), + UPB_TABVALUE_PTR_INIT("LITE_RUNTIME"), }; static const upb_symtab symtab = UPB_SYMTAB_INIT(UPB_STRTABLE_INIT(24, 31, UPB_CTYPE_PTR, 5, &strentries[204]), &reftables[210], &reftables[211]); @@ -5798,8 +5877,8 @@ static upb_inttable reftables[212] = { #include <stdlib.h> #include <string.h> -// upb_deflist is an internal-only dynamic array for storing a growing list of -// upb_defs. +/* upb_deflist is an internal-only dynamic array for storing a growing list of + * upb_defs. */ typedef struct { upb_def **defs; size_t len; @@ -5807,27 +5886,27 @@ typedef struct { bool owned; } upb_deflist; -// We keep a stack of all the messages scopes we are currently in, as well as -// the top-level file scope. This is necessary to correctly qualify the -// definitions that are contained inside. "name" tracks the name of the -// message or package (a bare name -- not qualified by any enclosing scopes). +/* We keep a stack of all the messages scopes we are currently in, as well as + * the top-level file scope. This is necessary to correctly qualify the + * definitions that are contained inside. "name" tracks the name of the + * message or package (a bare name -- not qualified by any enclosing scopes). */ typedef struct { char *name; - // Index of the first def that is under this scope. For msgdefs, the - // msgdef itself is at start-1. + /* Index of the first def that is under this scope. For msgdefs, the + * msgdef itself is at start-1. */ int start; } upb_descreader_frame; -// The maximum number of nested declarations that are allowed, ie. -// message Foo { -// message Bar { -// message Baz { -// } -// } -// } -// -// This is a resource limit that affects how big our runtime stack can grow. -// TODO: make this a runtime-settable property of the Reader instance. +/* The maximum number of nested declarations that are allowed, ie. + * message Foo { + * message Bar { + * message Baz { + * } + * } + * } + * + * This is a resource limit that affects how big our runtime stack can grow. + * TODO: make this a runtime-settable property of the Reader instance. */ #define UPB_MAX_MESSAGE_NESTING 64 struct upb_descreader { @@ -5854,11 +5933,11 @@ static char *upb_strndup(const char *buf, size_t n) { return ret; } -// Returns a newly allocated string that joins input strings together, for -// example: -// join("Foo.Bar", "Baz") -> "Foo.Bar.Baz" -// join("", "Baz") -> "Baz" -// Caller owns a ref on the returned string. +/* Returns a newly allocated string that joins input strings together, for + * example: + * join("Foo.Bar", "Baz") -> "Foo.Bar.Baz" + * join("", "Baz") -> "Baz" + * Caller owns a ref on the returned string. */ static char *upb_join(const char *base, const char *name) { if (!base || strlen(base) == 0) { return upb_strdup(name); @@ -5883,8 +5962,9 @@ void upb_deflist_init(upb_deflist *l) { } void upb_deflist_uninit(upb_deflist *l) { + size_t i; if (l->owned) - for(size_t i = 0; i < l->len; i++) + for(i = 0; i < l->len; i++) upb_def_unref(l->defs[i], l); free(l->defs); } @@ -5902,8 +5982,9 @@ bool upb_deflist_push(upb_deflist *l, upb_def *d) { } void upb_deflist_donaterefs(upb_deflist *l, void *owner) { + size_t i; assert(l->owned); - for (size_t i = 0; i < l->len; i++) + for (i = 0; i < l->len; i++) upb_def_donateref(l->defs[i], l, owner); l->owned = false; } @@ -5912,9 +5993,10 @@ static upb_def *upb_deflist_last(upb_deflist *l) { return l->defs[l->len-1]; } -// Qualify the defname for all defs starting with offset "start" with "str". +/* Qualify the defname for all defs starting with offset "start" with "str". */ static void upb_deflist_qualify(upb_deflist *l, char *str, int32_t start) { - for (uint32_t i = start; i < l->len; i++) { + uint32_t i; + for (i = start; i < l->len; i++) { upb_def *def = l->defs[i]; char *name = upb_join(str, upb_def_fullname(def)); upb_def_setfullname(def, name, NULL); @@ -5926,8 +6008,9 @@ static void upb_deflist_qualify(upb_deflist *l, char *str, int32_t start) { /* upb_descreader ************************************************************/ static upb_msgdef *upb_descreader_top(upb_descreader *r) { + int index; assert(r->stack_len > 1); - int index = r->stack[r->stack_len-1].start - 1; + index = r->stack[r->stack_len-1].start - 1; assert(index >= 0); return upb_downcast_msgdef_mutable(r->defs.defs[index]); } @@ -5936,8 +6019,8 @@ static upb_def *upb_descreader_last(upb_descreader *r) { return upb_deflist_last(&r->defs); } -// Start/end handlers for FileDescriptorProto and DescriptorProto (the two -// entities that have names and can contain sub-definitions. +/* Start/end handlers for FileDescriptorProto and DescriptorProto (the two + * entities that have names and can contain sub-definitions. */ void upb_descreader_startcontainer(upb_descreader *r) { upb_descreader_frame *f = &r->stack[r->stack_len++]; f->start = r->defs.len; @@ -5957,7 +6040,7 @@ void upb_descreader_setscopename(upb_descreader *r, char *str) { f->name = str; } -// Handlers for google.protobuf.FileDescriptorProto. +/* Handlers for google.protobuf.FileDescriptorProto. */ static bool file_startmsg(void *r, const void *hd) { UPB_UNUSED(hd); upb_descreader_startcontainer(r); @@ -5965,27 +6048,27 @@ static bool file_startmsg(void *r, const void *hd) { } static bool file_endmsg(void *closure, const void *hd, upb_status *status) { + upb_descreader *r = closure; UPB_UNUSED(hd); UPB_UNUSED(status); - upb_descreader *r = closure; upb_descreader_endcontainer(r); return true; } static size_t file_onpackage(void *closure, const void *hd, const char *buf, size_t n, const upb_bufhandle *handle) { + upb_descreader *r = closure; UPB_UNUSED(hd); UPB_UNUSED(handle); - upb_descreader *r = closure; - // XXX: see comment at the top of the file. + /* XXX: see comment at the top of the file. */ upb_descreader_setscopename(r, upb_strndup(buf, n)); return n; } -// Handlers for google.protobuf.EnumValueDescriptorProto. +/* Handlers for google.protobuf.EnumValueDescriptorProto. */ static bool enumval_startmsg(void *closure, const void *hd) { - UPB_UNUSED(hd); upb_descreader *r = closure; + UPB_UNUSED(hd); r->saw_number = false; r->saw_name = false; return true; @@ -5993,10 +6076,10 @@ static bool enumval_startmsg(void *closure, const void *hd) { static size_t enumval_onname(void *closure, const void *hd, const char *buf, size_t n, const upb_bufhandle *handle) { + upb_descreader *r = closure; UPB_UNUSED(hd); UPB_UNUSED(handle); - upb_descreader *r = closure; - // XXX: see comment at the top of the file. + /* XXX: see comment at the top of the file. */ free(r->name); r->name = upb_strndup(buf, n); r->saw_name = true; @@ -6004,21 +6087,23 @@ static size_t enumval_onname(void *closure, const void *hd, const char *buf, } static bool enumval_onnumber(void *closure, const void *hd, int32_t val) { - UPB_UNUSED(hd); upb_descreader *r = closure; + UPB_UNUSED(hd); r->number = val; r->saw_number = true; return true; } static bool enumval_endmsg(void *closure, const void *hd, upb_status *status) { - UPB_UNUSED(hd); upb_descreader *r = closure; + upb_enumdef *e; + UPB_UNUSED(hd); + if(!r->saw_number || !r->saw_name) { upb_status_seterrmsg(status, "Enum value missing name or number."); return false; } - upb_enumdef *e = upb_downcast_enumdef_mutable(upb_descreader_last(r)); + e = upb_downcast_enumdef_mutable(upb_descreader_last(r)); upb_enumdef_addval(e, r->name, r->number, status); free(r->name); r->name = NULL; @@ -6026,18 +6111,21 @@ static bool enumval_endmsg(void *closure, const void *hd, upb_status *status) { } -// Handlers for google.protobuf.EnumDescriptorProto. +/* Handlers for google.protobuf.EnumDescriptorProto. */ static bool enum_startmsg(void *closure, const void *hd) { - UPB_UNUSED(hd); upb_descreader *r = closure; - upb_deflist_push(&r->defs, UPB_UPCAST(upb_enumdef_new(&r->defs))); + UPB_UNUSED(hd); + upb_deflist_push(&r->defs, + upb_enumdef_upcast_mutable(upb_enumdef_new(&r->defs))); return true; } static bool enum_endmsg(void *closure, const void *hd, upb_status *status) { - UPB_UNUSED(hd); upb_descreader *r = closure; - upb_enumdef *e = upb_downcast_enumdef_mutable(upb_descreader_last(r)); + upb_enumdef *e; + UPB_UNUSED(hd); + + e = upb_downcast_enumdef_mutable(upb_descreader_last(r)); if (upb_def_fullname(upb_descreader_last(r)) == NULL) { upb_status_seterrmsg(status, "Enum had no name."); return false; @@ -6051,31 +6139,31 @@ static bool enum_endmsg(void *closure, const void *hd, upb_status *status) { static size_t enum_onname(void *closure, const void *hd, const char *buf, size_t n, const upb_bufhandle *handle) { - UPB_UNUSED(hd); - UPB_UNUSED(handle); upb_descreader *r = closure; - // XXX: see comment at the top of the file. char *fullname = upb_strndup(buf, n); + UPB_UNUSED(hd); + UPB_UNUSED(handle); + /* XXX: see comment at the top of the file. */ upb_def_setfullname(upb_descreader_last(r), fullname, NULL); free(fullname); return n; } -// Handlers for google.protobuf.FieldDescriptorProto +/* Handlers for google.protobuf.FieldDescriptorProto */ static bool field_startmsg(void *closure, const void *hd) { - UPB_UNUSED(hd); upb_descreader *r = closure; + UPB_UNUSED(hd); r->f = upb_fielddef_new(&r->defs); free(r->default_string); r->default_string = NULL; - // fielddefs default to packed, but descriptors default to non-packed. + /* fielddefs default to packed, but descriptors default to non-packed. */ upb_fielddef_setpacked(r->f, false); return true; } -// Converts the default value in string "str" into "d". Passes a ref on str. -// Returns true on success. +/* Converts the default value in string "str" into "d". Passes a ref on str. + * Returns true on success. */ static bool parse_default(char *str, upb_fielddef *f) { bool success = true; char *end; @@ -6089,7 +6177,8 @@ static bool parse_default(char *str, upb_fielddef *f) { break; } case UPB_TYPE_INT64: { - long long val = strtoll(str, &end, 0); + /* XXX: Need to write our own strtoll, since it's not available in c89. */ + long long val = strtol(str, &end, 0); if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || *end) success = false; else @@ -6105,7 +6194,8 @@ static bool parse_default(char *str, upb_fielddef *f) { break; } case UPB_TYPE_UINT64: { - unsigned long long val = strtoull(str, &end, 0); + /* XXX: Need to write our own strtoull, since it's not available in c89. */ + unsigned long long val = strtoul(str, &end, 0); if (val > UINT64_MAX || errno == ERANGE || *end) success = false; else @@ -6121,7 +6211,8 @@ static bool parse_default(char *str, upb_fielddef *f) { break; } case UPB_TYPE_FLOAT: { - float val = strtof(str, &end); + /* XXX: Need to write our own strtof, since it's not available in c89. */ + float val = strtod(str, &end); if (errno == ERANGE || *end) success = false; else @@ -6143,10 +6234,11 @@ static bool parse_default(char *str, upb_fielddef *f) { } static bool field_endmsg(void *closure, const void *hd, upb_status *status) { - UPB_UNUSED(hd); upb_descreader *r = closure; upb_fielddef *f = r->f; - // TODO: verify that all required fields were present. + UPB_UNUSED(hd); + + /* TODO: verify that all required fields were present. */ assert(upb_fielddef_number(f) != 0); assert(upb_fielddef_name(f) != NULL); assert((upb_fielddef_subdefname(f) != NULL) == upb_fielddef_hassubdef(f)); @@ -6160,8 +6252,8 @@ static bool field_endmsg(void *closure, const void *hd, upb_status *status) { upb_fielddef_setdefaultcstr(f, r->default_string, NULL); } else { if (r->default_string && !parse_default(r->default_string, f)) { - // We don't worry too much about giving a great error message since the - // compiler should have ensured this was correct. + /* We don't worry too much about giving a great error message since the + * compiler should have ensured this was correct. */ upb_status_seterrmsg(status, "Error converting default value."); return false; } @@ -6171,48 +6263,54 @@ static bool field_endmsg(void *closure, const void *hd, upb_status *status) { } static bool field_onlazy(void *closure, const void *hd, bool val) { - UPB_UNUSED(hd); upb_descreader *r = closure; + UPB_UNUSED(hd); + upb_fielddef_setlazy(r->f, val); return true; } static bool field_onpacked(void *closure, const void *hd, bool val) { - UPB_UNUSED(hd); upb_descreader *r = closure; + UPB_UNUSED(hd); + upb_fielddef_setpacked(r->f, val); return true; } static bool field_ontype(void *closure, const void *hd, int32_t val) { - UPB_UNUSED(hd); upb_descreader *r = closure; + UPB_UNUSED(hd); + upb_fielddef_setdescriptortype(r->f, val); return true; } static bool field_onlabel(void *closure, const void *hd, int32_t val) { - UPB_UNUSED(hd); upb_descreader *r = closure; + UPB_UNUSED(hd); + upb_fielddef_setlabel(r->f, val); return true; } static bool field_onnumber(void *closure, const void *hd, int32_t val) { - UPB_UNUSED(hd); upb_descreader *r = closure; bool ok = upb_fielddef_setnumber(r->f, val, NULL); + UPB_UNUSED(hd); + UPB_ASSERT_VAR(ok, ok); return true; } static size_t field_onname(void *closure, const void *hd, const char *buf, size_t n, const upb_bufhandle *handle) { - UPB_UNUSED(hd); - UPB_UNUSED(handle); upb_descreader *r = closure; - // XXX: see comment at the top of the file. char *name = upb_strndup(buf, n); + UPB_UNUSED(hd); + UPB_UNUSED(handle); + + /* XXX: see comment at the top of the file. */ upb_fielddef_setname(r->f, name, NULL); free(name); return n; @@ -6220,11 +6318,12 @@ static size_t field_onname(void *closure, const void *hd, const char *buf, static size_t field_ontypename(void *closure, const void *hd, const char *buf, size_t n, const upb_bufhandle *handle) { - UPB_UNUSED(hd); - UPB_UNUSED(handle); upb_descreader *r = closure; - // XXX: see comment at the top of the file. char *name = upb_strndup(buf, n); + UPB_UNUSED(hd); + UPB_UNUSED(handle); + + /* XXX: see comment at the top of the file. */ upb_fielddef_setsubdefname(r->f, name, NULL); free(name); return n; @@ -6232,11 +6331,12 @@ static size_t field_ontypename(void *closure, const void *hd, const char *buf, static size_t field_onextendee(void *closure, const void *hd, const char *buf, size_t n, const upb_bufhandle *handle) { - UPB_UNUSED(hd); - UPB_UNUSED(handle); upb_descreader *r = closure; - // XXX: see comment at the top of the file. char *name = upb_strndup(buf, n); + UPB_UNUSED(hd); + UPB_UNUSED(handle); + + /* XXX: see comment at the top of the file. */ upb_fielddef_setcontainingtypename(r->f, name, NULL); free(name); return n; @@ -6244,31 +6344,35 @@ static size_t field_onextendee(void *closure, const void *hd, const char *buf, static size_t field_ondefaultval(void *closure, const void *hd, const char *buf, size_t n, const upb_bufhandle *handle) { + upb_descreader *r = closure; UPB_UNUSED(hd); UPB_UNUSED(handle); - upb_descreader *r = closure; - // Have to convert from string to the correct type, but we might not know the - // type yet, so we save it as a string until the end of the field. - // XXX: see comment at the top of the file. + + /* Have to convert from string to the correct type, but we might not know the + * type yet, so we save it as a string until the end of the field. + * XXX: see comment at the top of the file. */ free(r->default_string); r->default_string = upb_strndup(buf, n); return n; } -// Handlers for google.protobuf.DescriptorProto (representing a message). +/* Handlers for google.protobuf.DescriptorProto (representing a message). */ static bool msg_startmsg(void *closure, const void *hd) { - UPB_UNUSED(hd); upb_descreader *r = closure; - upb_deflist_push(&r->defs, UPB_UPCAST(upb_msgdef_new(&r->defs))); + UPB_UNUSED(hd); + + upb_deflist_push(&r->defs, + upb_msgdef_upcast_mutable(upb_msgdef_new(&r->defs))); upb_descreader_startcontainer(r); return true; } static bool msg_endmsg(void *closure, const void *hd, upb_status *status) { - UPB_UNUSED(hd); upb_descreader *r = closure; upb_msgdef *m = upb_descreader_top(r); - if(!upb_def_fullname(UPB_UPCAST(m))) { + UPB_UNUSED(hd); + + if(!upb_def_fullname(upb_msgdef_upcast_mutable(m))) { upb_status_seterrmsg(status, "Encountered message with no name."); return false; } @@ -6278,32 +6382,35 @@ static bool msg_endmsg(void *closure, const void *hd, upb_status *status) { static size_t msg_onname(void *closure, const void *hd, const char *buf, size_t n, const upb_bufhandle *handle) { - UPB_UNUSED(hd); - UPB_UNUSED(handle); upb_descreader *r = closure; upb_msgdef *m = upb_descreader_top(r); - // XXX: see comment at the top of the file. + /* XXX: see comment at the top of the file. */ char *name = upb_strndup(buf, n); - upb_def_setfullname(UPB_UPCAST(m), name, NULL); - upb_descreader_setscopename(r, name); // Passes ownership of name. + UPB_UNUSED(hd); + UPB_UNUSED(handle); + + upb_def_setfullname(upb_msgdef_upcast_mutable(m), name, NULL); + upb_descreader_setscopename(r, name); /* Passes ownership of name. */ return n; } static bool msg_onendfield(void *closure, const void *hd) { - UPB_UNUSED(hd); upb_descreader *r = closure; upb_msgdef *m = upb_descreader_top(r); + UPB_UNUSED(hd); + upb_msgdef_addfield(m, r->f, &r->defs, NULL); r->f = NULL; return true; } static bool pushextension(void *closure, const void *hd) { - UPB_UNUSED(hd); upb_descreader *r = closure; + UPB_UNUSED(hd); + assert(upb_fielddef_containingtypename(r->f)); upb_fielddef_setisextension(r->f, true); - upb_deflist_push(&r->defs, UPB_UPCAST(r->f)); + upb_deflist_push(&r->defs, upb_fielddef_upcast_mutable(r->f)); r->f = NULL; return true; } @@ -6455,14 +6562,14 @@ static void visitgroup(const upb_refcounted *r, upb_refcounted_visit *visit, upb_inttable_begin(&i, &g->methods); for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i)); - visit(r, UPB_UPCAST(method), closure); + visit(r, upb_pbdecodermethod_upcast(method), closure); } } mgroup *newgroup(const void *owner) { mgroup *g = malloc(sizeof(*g)); static const struct upb_refcounted_vtbl vtbl = {visitgroup, freegroup}; - upb_refcounted_init(UPB_UPCAST(g), &vtbl, owner); + upb_refcounted_init(mgroup_upcast_mutable(g), &vtbl, owner); upb_inttable_init(&g->methods, UPB_CTYPE_PTR); g->bytecode = NULL; g->bytecode_end = NULL; @@ -6493,18 +6600,18 @@ static upb_pbdecodermethod *newmethod(const upb_handlers *dest_handlers, mgroup *group) { static const struct upb_refcounted_vtbl vtbl = {visitmethod, freemethod}; upb_pbdecodermethod *ret = malloc(sizeof(*ret)); - upb_refcounted_init(UPB_UPCAST(ret), &vtbl, &ret); + upb_refcounted_init(upb_pbdecodermethod_upcast_mutable(ret), &vtbl, &ret); upb_byteshandler_init(&ret->input_handler_); - // The method references the group and vice-versa, in a circular reference. + /* The method references the group and vice-versa, in a circular reference. */ upb_ref2(ret, group); upb_ref2(group, ret); upb_inttable_insertptr(&group->methods, dest_handlers, upb_value_ptr(ret)); - upb_refcounted_unref(UPB_UPCAST(ret), &ret); + upb_pbdecodermethod_unref(ret, &ret); - ret->group = UPB_UPCAST(group); + ret->group = mgroup_upcast_mutable(group); ret->dest_handlers_ = dest_handlers; - ret->is_native_ = false; // If we JIT, it will update this later. + ret->is_native_ = false; /* If we JIT, it will update this later. */ upb_inttable_init(&ret->dispatch, UPB_CTYPE_UINT64); if (ret->dest_handlers_) { @@ -6513,25 +6620,6 @@ static upb_pbdecodermethod *newmethod(const upb_handlers *dest_handlers, return ret; } -void upb_pbdecodermethod_ref(const upb_pbdecodermethod *m, const void *owner) { - upb_refcounted_ref(UPB_UPCAST(m), owner); -} - -void upb_pbdecodermethod_unref(const upb_pbdecodermethod *m, - const void *owner) { - upb_refcounted_unref(UPB_UPCAST(m), owner); -} - -void upb_pbdecodermethod_donateref(const upb_pbdecodermethod *m, - const void *from, const void *to) { - upb_refcounted_donateref(UPB_UPCAST(m), from, to); -} - -void upb_pbdecodermethod_checkref(const upb_pbdecodermethod *m, - const void *owner) { - upb_refcounted_checkref(UPB_UPCAST(m), owner); -} - const upb_handlers *upb_pbdecodermethod_desthandlers( const upb_pbdecodermethod *m) { return m->dest_handlers_; @@ -6548,10 +6636,11 @@ bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m) { const upb_pbdecodermethod *upb_pbdecodermethod_new( const upb_pbdecodermethodopts *opts, const void *owner) { + const upb_pbdecodermethod *ret; upb_pbcodecache cache; + upb_pbcodecache_init(&cache); - const upb_pbdecodermethod *ret = - upb_pbcodecache_getdecodermethod(&cache, opts); + ret = upb_pbcodecache_getdecodermethod(&cache, opts); upb_pbdecodermethod_ref(ret, owner); upb_pbcodecache_uninit(&cache); return ret; @@ -6560,7 +6649,7 @@ const upb_pbdecodermethod *upb_pbdecodermethod_new( /* bytecode compiler **********************************************************/ -// Data used only at compilation time. +/* Data used only at compilation time. */ typedef struct { mgroup *group; @@ -6568,15 +6657,17 @@ typedef struct { int fwd_labels[MAXLABEL]; int back_labels[MAXLABEL]; - // For fields marked "lazy", parse them lazily or eagerly? + /* For fields marked "lazy", parse them lazily or eagerly? */ bool lazy; } compiler; static compiler *newcompiler(mgroup *group, bool lazy) { compiler *ret = malloc(sizeof(*ret)); + int i; + ret->group = group; ret->lazy = lazy; - for (int i = 0; i < MAXLABEL; i++) { + for (i = 0; i < MAXLABEL; i++) { ret->fwd_labels[i] = EMPTYLABEL; ret->back_labels[i] = EMPTYLABEL; } @@ -6589,7 +6680,7 @@ static void freecompiler(compiler *c) { const size_t ptr_words = sizeof(void*) / sizeof(uint32_t); -// How many words an instruction is. +/* How many words an instruction is. */ static int instruction_len(uint32_t instr) { switch (getop(instr)) { case OP_SETDISPATCH: return 1 + ptr_words; @@ -6605,8 +6696,8 @@ bool op_has_longofs(int32_t instruction) { case OP_BRANCH: case OP_CHECKDELIM: return true; - // The "tag" instructions only have 8 bytes available for the jump target, - // but that is ok because these opcodes only require short jumps. + /* The "tag" instructions only have 8 bytes available for the jump target, + * but that is ok because these opcodes only require short jumps. */ case OP_TAG1: case OP_TAG2: case OP_TAGN: @@ -6631,18 +6722,21 @@ static void setofs(uint32_t *instruction, int32_t ofs) { } else { *instruction = (*instruction & ~0xff00) | ((ofs & 0xff) << 8); } - assert(getofs(*instruction) == ofs); // Would fail in cases of overflow. + assert(getofs(*instruction) == ofs); /* Would fail in cases of overflow. */ } static uint32_t pcofs(compiler *c) { return c->pc - c->group->bytecode; } -// Defines a local label at the current PC location. All previous forward -// references are updated to point to this location. The location is noted -// for any future backward references. +/* Defines a local label at the current PC location. All previous forward + * references are updated to point to this location. The location is noted + * for any future backward references. */ static void label(compiler *c, unsigned int label) { + int val; + uint32_t *codep; + assert(label < MAXLABEL); - int val = c->fwd_labels[label]; - uint32_t *codep = (val == EMPTYLABEL) ? NULL : c->group->bytecode + val; + val = c->fwd_labels[label]; + codep = (val == EMPTYLABEL) ? NULL : c->group->bytecode + val; while (codep) { int ofs = getofs(*codep); setofs(codep, c->pc - codep - instruction_len(*codep)); @@ -6652,24 +6746,25 @@ static void label(compiler *c, unsigned int label) { c->back_labels[label] = pcofs(c); } -// Creates a reference to a numbered label; either a forward reference -// (positive arg) or backward reference (negative arg). For forward references -// the value returned now is actually a "next" pointer into a linked list of all -// instructions that use this label and will be patched later when the label is -// defined with label(). -// -// The returned value is the offset that should be written into the instruction. +/* Creates a reference to a numbered label; either a forward reference + * (positive arg) or backward reference (negative arg). For forward references + * the value returned now is actually a "next" pointer into a linked list of all + * instructions that use this label and will be patched later when the label is + * defined with label(). + * + * The returned value is the offset that should be written into the instruction. + */ static int32_t labelref(compiler *c, int label) { assert(label < MAXLABEL); if (label == LABEL_DISPATCH) { - // No resolving required. + /* No resolving required. */ return 0; } else if (label < 0) { - // Backward local label. Relative to the next instruction. + /* Backward local label. Relative to the next instruction. */ uint32_t from = (c->pc + 1) - c->group->bytecode; return c->back_labels[-label] - from; } else { - // Forward local label: prepend to (possibly-empty) linked list. + /* Forward local label: prepend to (possibly-empty) linked list. */ int *lptr = &c->fwd_labels[label]; int32_t ret = (*lptr == EMPTYLABEL) ? 0 : *lptr - pcofs(c); *lptr = pcofs(c); @@ -6683,7 +6778,7 @@ static void put32(compiler *c, uint32_t v) { int ofs = pcofs(c); size_t oldsize = g->bytecode_end - g->bytecode; size_t newsize = UPB_MAX(oldsize * 2, 64); - // TODO(haberman): handle OOM. + /* TODO(haberman): handle OOM. */ g->bytecode = realloc(g->bytecode, newsize * sizeof(uint32_t)); g->bytecode_end = g->bytecode + newsize; c->pc = g->bytecode + ofs; @@ -6782,19 +6877,22 @@ static void putop(compiler *c, opcode op, ...) { #if defined(UPB_USE_JIT_X64) || defined(UPB_DUMP_BYTECODE) const char *upb_pbdecoder_getopname(unsigned int op) { -#define OP(op) [OP_ ## op] = "OP_" #op -#define T(op) OP(PARSE_##op) - static const char *names[] = { - "<no opcode>", - T(DOUBLE), T(FLOAT), T(INT64), T(UINT64), T(INT32), T(FIXED64), T(FIXED32), - T(BOOL), T(UINT32), T(SFIXED32), T(SFIXED64), T(SINT32), T(SINT64), - OP(STARTMSG), OP(ENDMSG), OP(STARTSEQ), OP(ENDSEQ), OP(STARTSUBMSG), - OP(ENDSUBMSG), OP(STARTSTR), OP(STRING), OP(ENDSTR), OP(CALL), OP(RET), - OP(PUSHLENDELIM), OP(PUSHTAGDELIM), OP(SETDELIM), OP(CHECKDELIM), - OP(BRANCH), OP(TAG1), OP(TAG2), OP(TAGN), OP(SETDISPATCH), OP(POP), - OP(SETBIGGROUPNUM), OP(DISPATCH), OP(HALT), - }; - return op > OP_HALT ? names[0] : names[op]; +#define QUOTE(x) #x +#define EXPAND_AND_QUOTE(x) QUOTE(x) +#define OPNAME(x) OP_##x +#define OP(x) case OPNAME(x): return EXPAND_AND_QUOTE(OPNAME(x)); +#define T(x) OP(PARSE_##x) + /* Keep in sync with list in decoder.int.h. */ + switch ((opcode)op) { + T(DOUBLE) T(FLOAT) T(INT64) T(UINT64) T(INT32) T(FIXED64) T(FIXED32) + T(BOOL) T(UINT32) T(SFIXED32) T(SFIXED64) T(SINT32) T(SINT64) + OP(STARTMSG) OP(ENDMSG) OP(STARTSEQ) OP(ENDSEQ) OP(STARTSUBMSG) + OP(ENDSUBMSG) OP(STARTSTR) OP(STRING) OP(ENDSTR) OP(CALL) OP(RET) + OP(PUSHLENDELIM) OP(PUSHTAGDELIM) OP(SETDELIM) OP(CHECKDELIM) + OP(BRANCH) OP(TAG1) OP(TAG2) OP(TAGN) OP(SETDISPATCH) OP(POP) + OP(SETBIGGROUPNUM) OP(DISPATCH) OP(HALT) + } + return "<unknown op>"; #undef OP #undef T } @@ -6892,7 +6990,7 @@ static void dumpbc(uint32_t *p, uint32_t *end, FILE *f) { static uint64_t get_encoded_tag(const upb_fielddef *f, int wire_type) { uint32_t tag = (upb_fielddef_number(f) << 3) | wire_type; uint64_t encoded_tag = upb_vencode32(tag); - // No tag should be greater than 5 bytes. + /* No tag should be greater than 5 bytes. */ assert(encoded_tag <= 0xffffffffff); return encoded_tag; } @@ -6920,29 +7018,29 @@ static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) { return selector; } -// Takes an existing, primary dispatch table entry and repacks it with a -// different alternate wire type. Called when we are inserting a secondary -// dispatch table entry for an alternate wire type. +/* Takes an existing, primary dispatch table entry and repacks it with a + * different alternate wire type. Called when we are inserting a secondary + * dispatch table entry for an alternate wire type. */ static uint64_t repack(uint64_t dispatch, int new_wt2) { uint64_t ofs; uint8_t wt1; uint8_t old_wt2; upb_pbdecoder_unpackdispatch(dispatch, &ofs, &wt1, &old_wt2); - assert(old_wt2 == NO_WIRE_TYPE); // wt2 should not be set yet. + assert(old_wt2 == NO_WIRE_TYPE); /* wt2 should not be set yet. */ return upb_pbdecoder_packdispatch(ofs, wt1, new_wt2); } -// Marks the current bytecode position as the dispatch target for this message, -// field, and wire type. +/* Marks the current bytecode position as the dispatch target for this message, + * field, and wire type. */ static void dispatchtarget(compiler *c, upb_pbdecodermethod *method, const upb_fielddef *f, int wire_type) { - // Offset is relative to msg base. + /* Offset is relative to msg base. */ uint64_t ofs = pcofs(c) - method->code_base.ofs; uint32_t fn = upb_fielddef_number(f); upb_inttable *d = &method->dispatch; upb_value v; if (upb_inttable_remove(d, fn, &v)) { - // TODO: prioritize based on packed setting in .proto file. + /* TODO: prioritize based on packed setting in .proto file. */ uint64_t repacked = repack(upb_value_getuint64(v), wire_type); upb_inttable_insert(d, fn, upb_value_uint64(repacked)); upb_inttable_insert(d, fn + UPB_MAX_FIELDNUMBER, upb_value_uint64(ofs)); @@ -6984,8 +7082,8 @@ static void putsel(compiler *c, opcode op, upb_selector_t sel, } } -// Puts an opcode to call a callback, but only if a callback actually exists for -// this field and handler type. +/* Puts an opcode to call a callback, but only if a callback actually exists for + * this field and handler type. */ static void maybeput(compiler *c, opcode op, const upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type) { putsel(c, op, getsel(f, type), h); @@ -7003,27 +7101,28 @@ static bool haslazyhandlers(const upb_handlers *h, const upb_fielddef *f) { /* bytecode compiler code generation ******************************************/ -// Symbolic names for our local labels. -#define LABEL_LOOPSTART 1 // Top of a repeated field loop. -#define LABEL_LOOPBREAK 2 // To jump out of a repeated loop -#define LABEL_FIELD 3 // Jump backward to find the most recent field. -#define LABEL_ENDMSG 4 // To reach the OP_ENDMSG instr for this msg. +/* Symbolic names for our local labels. */ +#define LABEL_LOOPSTART 1 /* Top of a repeated field loop. */ +#define LABEL_LOOPBREAK 2 /* To jump out of a repeated loop */ +#define LABEL_FIELD 3 /* Jump backward to find the most recent field. */ +#define LABEL_ENDMSG 4 /* To reach the OP_ENDMSG instr for this msg. */ -// Generates bytecode to parse a single non-lazy message field. +/* Generates bytecode to parse a single non-lazy message field. */ static void generate_msgfield(compiler *c, const upb_fielddef *f, upb_pbdecodermethod *method) { const upb_handlers *h = upb_pbdecodermethod_desthandlers(method); const upb_pbdecodermethod *sub_m = find_submethod(c, method, f); + int wire_type; if (!sub_m) { - // Don't emit any code for this field at all; it will be parsed as an - // unknown field. + /* Don't emit any code for this field at all; it will be parsed as an + * unknown field. */ return; } label(c, LABEL_FIELD); - int wire_type = + wire_type = (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE) ? UPB_WIRE_TYPE_DELIMITED : UPB_WIRE_TYPE_START_GROUP; @@ -7064,7 +7163,7 @@ static void generate_msgfield(compiler *c, const upb_fielddef *f, } } -// Generates bytecode to parse a single string or lazy submessage field. +/* Generates bytecode to parse a single string or lazy submessage field. */ static void generate_delimfield(compiler *c, const upb_fielddef *f, upb_pbdecodermethod *method) { const upb_handlers *h = upb_pbdecodermethod_desthandlers(method); @@ -7079,7 +7178,7 @@ static void generate_delimfield(compiler *c, const upb_fielddef *f, label(c, LABEL_LOOPSTART); putop(c, OP_PUSHLENDELIM); putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR)); - // Need to emit even if no handler to skip past the string. + /* Need to emit even if no handler to skip past the string. */ putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING)); putop(c, OP_POP); maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR); @@ -7103,49 +7202,52 @@ static void generate_delimfield(compiler *c, const upb_fielddef *f, } } -// Generates bytecode to parse a single primitive field. +/* Generates bytecode to parse a single primitive field. */ static void generate_primitivefield(compiler *c, const upb_fielddef *f, upb_pbdecodermethod *method) { - label(c, LABEL_FIELD); - const upb_handlers *h = upb_pbdecodermethod_desthandlers(method); upb_descriptortype_t descriptor_type = upb_fielddef_descriptortype(f); + opcode parse_type; + upb_selector_t sel; + int wire_type; + + label(c, LABEL_FIELD); - // From a decoding perspective, ENUM is the same as INT32. + /* From a decoding perspective, ENUM is the same as INT32. */ if (descriptor_type == UPB_DESCRIPTOR_TYPE_ENUM) descriptor_type = UPB_DESCRIPTOR_TYPE_INT32; - opcode parse_type = (opcode)descriptor_type; + parse_type = (opcode)descriptor_type; - // TODO(haberman): generate packed or non-packed first depending on "packed" - // setting in the fielddef. This will favor (in speed) whichever was - // specified. + /* TODO(haberman): generate packed or non-packed first depending on "packed" + * setting in the fielddef. This will favor (in speed) whichever was + * specified. */ assert((int)parse_type >= 0 && parse_type <= OP_MAX); - upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); - int wire_type = upb_pb_native_wire_types[upb_fielddef_descriptortype(f)]; + sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); + wire_type = upb_pb_native_wire_types[upb_fielddef_descriptortype(f)]; if (upb_fielddef_isseq(f)) { putop(c, OP_CHECKDELIM, LABEL_ENDMSG); putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH); dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED); putop(c, OP_PUSHLENDELIM); - putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ)); // Packed + putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ)); /* Packed */ label(c, LABEL_LOOPSTART); putop(c, parse_type, sel); putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK); putop(c, OP_BRANCH, -LABEL_LOOPSTART); dispatchtarget(c, method, f, wire_type); putop(c, OP_PUSHTAGDELIM, 0); - putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ)); // Non-packed + putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ)); /* Non-packed */ label(c, LABEL_LOOPSTART); putop(c, parse_type, sel); putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK); putchecktag(c, f, wire_type, LABEL_LOOPBREAK); putop(c, OP_BRANCH, -LABEL_LOOPSTART); label(c, LABEL_LOOPBREAK); - putop(c, OP_POP); // Packed and non-packed join. + putop(c, OP_POP); /* Packed and non-packed join. */ maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ); - putop(c, OP_SETDELIM); // Could remove for non-packed by dup ENDSEQ. + putop(c, OP_SETDELIM); /* Could remove for non-packed by dup ENDSEQ. */ } else { putop(c, OP_CHECKDELIM, LABEL_ENDMSG); putchecktag(c, f, wire_type, LABEL_DISPATCH); @@ -7154,24 +7256,29 @@ static void generate_primitivefield(compiler *c, const upb_fielddef *f, } } -// Adds bytecode for parsing the given message to the given decoderplan, -// while adding all dispatch targets to this message's dispatch table. +/* Adds bytecode for parsing the given message to the given decoderplan, + * while adding all dispatch targets to this message's dispatch table. */ static void compile_method(compiler *c, upb_pbdecodermethod *method) { + const upb_handlers *h; + const upb_msgdef *md; + uint32_t* start_pc; + upb_msg_field_iter i; + upb_value val; + assert(method); - // Clear all entries in the dispatch table. + /* Clear all entries in the dispatch table. */ upb_inttable_uninit(&method->dispatch); upb_inttable_init(&method->dispatch, UPB_CTYPE_UINT64); - const upb_handlers *h = upb_pbdecodermethod_desthandlers(method); - const upb_msgdef *md = upb_handlers_msgdef(h); + h = upb_pbdecodermethod_desthandlers(method); + md = upb_handlers_msgdef(h); method->code_base.ofs = pcofs(c); putop(c, OP_SETDISPATCH, &method->dispatch); putsel(c, OP_STARTMSG, UPB_STARTMSG_SELECTOR, h); label(c, LABEL_FIELD); - uint32_t* start_pc = c->pc; - upb_msg_field_iter i; + start_pc = c->pc; for(upb_msg_field_begin(&i, md); !upb_msg_field_done(&i); upb_msg_field_next(&i)) { @@ -7188,23 +7295,23 @@ static void compile_method(compiler *c, upb_pbdecodermethod *method) { } } - // If there were no fields, or if no handlers were defined, we need to - // generate a non-empty loop body so that we can at least dispatch for unknown - // fields and check for the end of the message. + /* If there were no fields, or if no handlers were defined, we need to + * generate a non-empty loop body so that we can at least dispatch for unknown + * fields and check for the end of the message. */ if (c->pc == start_pc) { - // Check for end-of-message. + /* Check for end-of-message. */ putop(c, OP_CHECKDELIM, LABEL_ENDMSG); - // Unconditionally dispatch. + /* Unconditionally dispatch. */ putop(c, OP_DISPATCH, 0); } - // For now we just loop back to the last field of the message (or if none, - // the DISPATCH opcode for the message). + /* For now we just loop back to the last field of the message (or if none, + * the DISPATCH opcode for the message). */ putop(c, OP_BRANCH, -LABEL_FIELD); - // Insert both a label and a dispatch table entry for this end-of-msg. + /* Insert both a label and a dispatch table entry for this end-of-msg. */ label(c, LABEL_ENDMSG); - upb_value val = upb_value_uint64(pcofs(c) - method->code_base.ofs); + val = upb_value_uint64(pcofs(c) - method->code_base.ofs); upb_inttable_insert(&method->dispatch, DISPATCH_ENDMSG, val); putsel(c, OP_ENDMSG, UPB_ENDMSG_SELECTOR, h); @@ -7213,19 +7320,21 @@ static void compile_method(compiler *c, upb_pbdecodermethod *method) { upb_inttable_compact(&method->dispatch); } -// Populate "methods" with new upb_pbdecodermethod objects reachable from "h". -// Returns the method for these handlers. -// -// Generates a new method for every destination handlers reachable from "h". +/* Populate "methods" with new upb_pbdecodermethod objects reachable from "h". + * Returns the method for these handlers. + * + * Generates a new method for every destination handlers reachable from "h". */ static void find_methods(compiler *c, const upb_handlers *h) { upb_value v; + upb_msg_field_iter i; + const upb_msgdef *md; + if (upb_inttable_lookupptr(&c->group->methods, h, &v)) return; newmethod(h, c->group); - // Find submethods. - upb_msg_field_iter i; - const upb_msgdef *md = upb_handlers_msgdef(h); + /* Find submethods. */ + md = upb_handlers_msgdef(h); for(upb_msg_field_begin(&i, md); !upb_msg_field_done(&i); upb_msg_field_next(&i)) { @@ -7233,20 +7342,21 @@ static void find_methods(compiler *c, const upb_handlers *h) { const upb_handlers *sub_h; if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE && (sub_h = upb_handlers_getsubhandlers(h, f)) != NULL) { - // We only generate a decoder method for submessages with handlers. - // Others will be parsed as unknown fields. + /* We only generate a decoder method for submessages with handlers. + * Others will be parsed as unknown fields. */ find_methods(c, sub_h); } } } -// (Re-)compile bytecode for all messages in "msgs." -// Overwrites any existing bytecode in "c". +/* (Re-)compile bytecode for all messages in "msgs." + * Overwrites any existing bytecode in "c". */ static void compile_methods(compiler *c) { - // Start over at the beginning of the bytecode. + upb_inttable_iter i; + + /* Start over at the beginning of the bytecode. */ c->pc = c->group->bytecode; - upb_inttable_iter i; upb_inttable_begin(&i, &c->group->methods); for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i)); @@ -7259,10 +7369,10 @@ static void set_bytecode_handlers(mgroup *g) { upb_inttable_begin(&i, &g->methods); for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { upb_pbdecodermethod *m = upb_value_getptr(upb_inttable_iter_value(&i)); + upb_byteshandler *h = &m->input_handler_; m->code_base.ptr = g->bytecode + m->code_base.ofs; - upb_byteshandler *h = &m->input_handler_; upb_byteshandler_setstartstr(h, upb_pbdecoder_startbc, m->code_base.ptr); upb_byteshandler_setstring(h, upb_pbdecoder_decode, g); upb_byteshandler_setendstr(h, upb_pbdecoder_end, m); @@ -7277,53 +7387,58 @@ static void set_bytecode_handlers(mgroup *g) { static void sethandlers(mgroup *g, bool allowjit) { g->jit_code = NULL; if (allowjit) { - // Compile byte-code into machine code, create handlers. + /* Compile byte-code into machine code, create handlers. */ upb_pbdecoder_jit(g); } else { set_bytecode_handlers(g); } } -#else // UPB_USE_JIT_X64 +#else /* UPB_USE_JIT_X64 */ static void sethandlers(mgroup *g, bool allowjit) { - // No JIT compiled in; use bytecode handlers unconditionally. + /* No JIT compiled in; use bytecode handlers unconditionally. */ UPB_UNUSED(allowjit); set_bytecode_handlers(g); } -#endif // UPB_USE_JIT_X64 +#endif /* UPB_USE_JIT_X64 */ -// TODO(haberman): allow this to be constructed for an arbitrary set of dest -// handlers and other mgroups (but verify we have a transitive closure). +/* TODO(haberman): allow this to be constructed for an arbitrary set of dest + * handlers and other mgroups (but verify we have a transitive closure). */ const mgroup *mgroup_new(const upb_handlers *dest, bool allowjit, bool lazy, const void *owner) { + mgroup *g; + compiler *c; + UPB_UNUSED(allowjit); assert(upb_handlers_isfrozen(dest)); - mgroup *g = newgroup(owner); - compiler *c = newcompiler(g, lazy); + g = newgroup(owner); + c = newcompiler(g, lazy); find_methods(c, dest); - // We compile in two passes: - // 1. all messages are assigned relative offsets from the beginning of the - // bytecode (saved in method->code_base). - // 2. forwards OP_CALL instructions can be correctly linked since message - // offsets have been previously assigned. - // - // Could avoid the second pass by linking OP_CALL instructions somehow. + /* We compile in two passes: + * 1. all messages are assigned relative offsets from the beginning of the + * bytecode (saved in method->code_base). + * 2. forwards OP_CALL instructions can be correctly linked since message + * offsets have been previously assigned. + * + * Could avoid the second pass by linking OP_CALL instructions somehow. */ compile_methods(c); compile_methods(c); g->bytecode_end = c->pc; freecompiler(c); #ifdef UPB_DUMP_BYTECODE - FILE *f = fopen("/tmp/upb-bytecode", "wb"); - assert(f); - dumpbc(g->bytecode, g->bytecode_end, stderr); - dumpbc(g->bytecode, g->bytecode_end, f); - fclose(f); + { + FILE *f = fopen("/tmp/upb-bytecode", "wb"); + assert(f); + dumpbc(g->bytecode, g->bytecode_end, stderr); + dumpbc(g->bytecode, g->bytecode_end, f); + fclose(f); + } #endif sethandlers(g, allowjit); @@ -7343,7 +7458,7 @@ void upb_pbcodecache_uninit(upb_pbcodecache *c) { upb_inttable_begin(&i, &c->groups); for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { const mgroup *group = upb_value_getconstptr(upb_inttable_iter_value(&i)); - upb_refcounted_unref(UPB_UPCAST(group), c); + mgroup_unref(group, c); } upb_inttable_uninit(&c->groups); } @@ -7361,13 +7476,15 @@ bool upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow) { const upb_pbdecodermethod *upb_pbcodecache_getdecodermethod( upb_pbcodecache *c, const upb_pbdecodermethodopts *opts) { - // Right now we build a new DecoderMethod every time. - // TODO(haberman): properly cache methods by their true key. + upb_value v; + bool ok; + + /* Right now we build a new DecoderMethod every time. + * TODO(haberman): properly cache methods by their true key. */ const mgroup *g = mgroup_new(opts->handlers, c->allow_jit_, opts->lazy, c); upb_inttable_push(&c->groups, upb_value_constptr(g)); - upb_value v; - bool ok = upb_inttable_lookupptr(&g->methods, opts->handlers, &v); + ok = upb_inttable_lookupptr(&g->methods, opts->handlers, &v); UPB_ASSERT_VAR(ok, ok); return upb_value_getptr(v); } @@ -7413,17 +7530,17 @@ void upb_pbdecodermethodopts_setlazy(upb_pbdecodermethodopts *opts, bool lazy) { #define CHECK_SUSPEND(x) if (!(x)) return upb_pbdecoder_suspend(d); -// Error messages that are shared between the bytecode and JIT decoders. +/* Error messages that are shared between the bytecode and JIT decoders. */ const char *kPbDecoderStackOverflow = "Nesting too deep."; -// Error messages shared within this file. +/* Error messages shared within this file. */ static const char *kUnterminatedVarint = "Unterminated varint."; /* upb_pbdecoder **************************************************************/ static opcode halt = OP_HALT; -// Whether an op consumes any of the input buffer. +/* Whether an op consumes any of the input buffer. */ static bool consumes_input(opcode op) { switch (op) { case OP_SETDISPATCH: @@ -7451,12 +7568,12 @@ static bool consumes_input(opcode op) { static bool in_residual_buf(const upb_pbdecoder *d, const char *p); -// It's unfortunate that we have to micro-manage the compiler with -// UPB_FORCEINLINE and UPB_NOINLINE, especially since this tuning is necessarily -// specific to one hardware configuration. But empirically on a Core i7, -// performance increases 30-50% with these annotations. Every instance where -// these appear, gcc 4.2.1 made the wrong decision and degraded performance in -// benchmarks. +/* It's unfortunate that we have to micro-manage the compiler with + * UPB_FORCEINLINE and UPB_NOINLINE, especially since this tuning is necessarily + * specific to one hardware configuration. But empirically on a Core i7, + * performance increases 30-50% with these annotations. Every instance where + * these appear, gcc 4.2.1 made the wrong decision and degraded performance in + * benchmarks. */ static void seterr(upb_pbdecoder *d, const char *msg) { upb_status status = UPB_STATUS_INIT; @@ -7471,22 +7588,22 @@ void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg) { /* Buffering ******************************************************************/ -// We operate on one buffer at a time, which is either the user's buffer passed -// to our "decode" callback or some residual bytes from the previous buffer. +/* We operate on one buffer at a time, which is either the user's buffer passed + * to our "decode" callback or some residual bytes from the previous buffer. */ -// How many bytes can be safely read from d->ptr without reading past end-of-buf -// or past the current delimited end. +/* How many bytes can be safely read from d->ptr without reading past end-of-buf + * or past the current delimited end. */ static size_t curbufleft(const upb_pbdecoder *d) { assert(d->data_end >= d->ptr); return d->data_end - d->ptr; } -// Overall stream offset of d->ptr. +/* Overall stream offset of d->ptr. */ uint64_t offset(const upb_pbdecoder *d) { return d->bufstart_ofs + (d->ptr - d->buf); } -// Advances d->ptr. +/* Advances d->ptr. */ static void advance(upb_pbdecoder *d, size_t len) { assert(curbufleft(d) >= len); d->ptr += len; @@ -7500,8 +7617,8 @@ static bool in_residual_buf(const upb_pbdecoder *d, const char *p) { return in_buf(p, d->residual, d->residual_end); } -// Calculates the delim_end value, which is affected by both the current buffer -// and the parsing stack, so must be called whenever either is updated. +/* Calculates the delim_end value, which is affected by both the current buffer + * and the parsing stack, so must be called whenever either is updated. */ static void set_delim_end(upb_pbdecoder *d) { size_t delim_ofs = d->top->end_ofs - d->bufstart_ofs; if (delim_ofs <= (size_t)(d->end - d->buf)) { @@ -7527,22 +7644,22 @@ static void advancetobuf(upb_pbdecoder *d, const char *buf, size_t len) { } static void checkpoint(upb_pbdecoder *d) { - // The assertion here is in the interests of efficiency, not correctness. - // We are trying to ensure that we don't checkpoint() more often than - // necessary. + /* The assertion here is in the interests of efficiency, not correctness. + * We are trying to ensure that we don't checkpoint() more often than + * necessary. */ assert(d->checkpoint != d->ptr); d->checkpoint = d->ptr; } -// Resumes the decoder from an initial state or from a previous suspend. +/* Resumes the decoder from an initial state or from a previous suspend. */ int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf, size_t size, const upb_bufhandle *handle) { - UPB_UNUSED(p); // Useless; just for the benefit of the JIT. + UPB_UNUSED(p); /* Useless; just for the benefit of the JIT. */ d->buf_param = buf; d->size_param = size; d->handle = handle; if (d->residual_end > d->residual) { - // We have residual bytes from the last buffer. + /* We have residual bytes from the last buffer. */ assert(d->ptr == d->residual); } else { switchtobuf(d, buf, buf + size); @@ -7555,18 +7672,20 @@ int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf, return DECODE_OK; } -// Suspends the decoder at the last checkpoint, without saving any residual -// bytes. If there are any unconsumed bytes, returns a short byte count. +/* Suspends the decoder at the last checkpoint, without saving any residual + * bytes. If there are any unconsumed bytes, returns a short byte count. */ size_t upb_pbdecoder_suspend(upb_pbdecoder *d) { d->pc = d->last; if (d->checkpoint == d->residual) { - // Checkpoint was in residual buf; no user bytes were consumed. + /* Checkpoint was in residual buf; no user bytes were consumed. */ d->ptr = d->residual; return 0; } else { + size_t consumed; assert(!in_residual_buf(d, d->checkpoint)); assert(d->buf == d->buf_param); - size_t consumed = d->checkpoint - d->buf; + + consumed = d->checkpoint - d->buf; d->bufstart_ofs += consumed; d->residual_end = d->residual; switchtobuf(d, d->residual, d->residual_end); @@ -7574,17 +7693,17 @@ size_t upb_pbdecoder_suspend(upb_pbdecoder *d) { } } -// Suspends the decoder at the last checkpoint, and saves any unconsumed -// bytes in our residual buffer. This is necessary if we need more user -// bytes to form a complete value, which might not be contiguous in the -// user's buffers. Always consumes all user bytes. +/* Suspends the decoder at the last checkpoint, and saves any unconsumed + * bytes in our residual buffer. This is necessary if we need more user + * bytes to form a complete value, which might not be contiguous in the + * user's buffers. Always consumes all user bytes. */ static size_t suspend_save(upb_pbdecoder *d) { - // We hit end-of-buffer before we could parse a full value. - // Save any unconsumed bytes (if any) to the residual buffer. + /* We hit end-of-buffer before we could parse a full value. + * Save any unconsumed bytes (if any) to the residual buffer. */ d->pc = d->last; if (d->checkpoint == d->residual) { - // Checkpoint was in residual buf; append user byte(s) to residual buf. + /* Checkpoint was in residual buf; append user byte(s) to residual buf. */ assert((d->residual_end - d->residual) + d->size_param <= sizeof(d->residual)); if (!in_residual_buf(d, d->ptr)) { @@ -7593,10 +7712,12 @@ static size_t suspend_save(upb_pbdecoder *d) { memcpy(d->residual_end, d->buf_param, d->size_param); d->residual_end += d->size_param; } else { - // Checkpoint was in user buf; old residual bytes not needed. + /* Checkpoint was in user buf; old residual bytes not needed. */ + size_t save; assert(!in_residual_buf(d, d->checkpoint)); + d->ptr = d->checkpoint; - size_t save = curbufleft(d); + save = curbufleft(d); assert(save <= sizeof(d->residual)); memcpy(d->residual, d->ptr, save); d->residual_end = d->residual + save; @@ -7607,19 +7728,21 @@ static size_t suspend_save(upb_pbdecoder *d) { return d->size_param; } -// Skips "bytes" bytes in the stream, which may be more than available. If we -// skip more bytes than are available, we return a long read count to the caller -// indicating how many bytes the caller should skip before passing a new buffer. +/* Skips "bytes" bytes in the stream, which may be more than available. If we + * skip more bytes than are available, we return a long read count to the caller + * indicating how many bytes the caller should skip before passing a new buffer. + */ static int32_t skip(upb_pbdecoder *d, size_t bytes) { assert(!in_residual_buf(d, d->ptr) || d->size_param == 0); if (curbufleft(d) >= bytes) { - // Skipped data is all in current buffer. + /* Skipped data is all in current buffer. */ advance(d, bytes); return DECODE_OK; } else { - // Skipped data extends beyond currently available buffers. + /* Skipped data extends beyond currently available buffers. */ + size_t skip; d->pc = d->last; - size_t skip = bytes - curbufleft(d); + skip = bytes - curbufleft(d); d->bufstart_ofs += (d->end - d->buf) + skip; d->residual_end = d->residual; switchtobuf(d, d->residual, d->residual_end); @@ -7627,8 +7750,8 @@ static int32_t skip(upb_pbdecoder *d, size_t bytes) { } } -// Copies the next "bytes" bytes into "buf" and advances the stream. -// Requires that this many bytes are available in the current buffer. +/* Copies the next "bytes" bytes into "buf" and advances the stream. + * Requires that this many bytes are available in the current buffer. */ UPB_FORCEINLINE static void consumebytes(upb_pbdecoder *d, void *buf, size_t bytes) { assert(bytes <= curbufleft(d)); @@ -7636,9 +7759,9 @@ UPB_FORCEINLINE static void consumebytes(upb_pbdecoder *d, void *buf, advance(d, bytes); } -// Slow path for getting the next "bytes" bytes, regardless of whether they are -// available in the current buffer or not. Returns a status code as described -// in decoder.int.h. +/* Slow path for getting the next "bytes" bytes, regardless of whether they are + * available in the current buffer or not. Returns a status code as described + * in decoder.int.h. */ UPB_NOINLINE static int32_t getbytes_slow(upb_pbdecoder *d, void *buf, size_t bytes) { const size_t avail = curbufleft(d); @@ -7659,12 +7782,13 @@ UPB_NOINLINE static int32_t getbytes_slow(upb_pbdecoder *d, void *buf, } } -// Gets the next "bytes" bytes, regardless of whether they are available in the -// current buffer or not. Returns a status code as described in decoder.int.h. +/* Gets the next "bytes" bytes, regardless of whether they are available in the + * current buffer or not. Returns a status code as described in decoder.int.h. + */ UPB_FORCEINLINE static int32_t getbytes(upb_pbdecoder *d, void *buf, size_t bytes) { if (curbufleft(d) >= bytes) { - // Buffer has enough data to satisfy. + /* Buffer has enough data to satisfy. */ consumebytes(d, buf, bytes); return DECODE_OK; } else { @@ -7697,13 +7821,13 @@ UPB_FORCEINLINE static size_t peekbytes(upb_pbdecoder *d, void *buf, /* Decoding of wire types *****************************************************/ -// Slow path for decoding a varint from the current buffer position. -// Returns a status code as described in decoder.int.h. +/* Slow path for decoding a varint from the current buffer position. + * Returns a status code as described in decoder.int.h. */ UPB_NOINLINE int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d, uint64_t *u64) { - *u64 = 0; uint8_t byte = 0x80; int bitpos; + *u64 = 0; for(bitpos = 0; bitpos < 70 && (byte & 0x80); bitpos += 7) { int32_t ret = getbytes(d, &byte, 1); if (ret >= 0) return ret; @@ -7716,15 +7840,15 @@ UPB_NOINLINE int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d, return DECODE_OK; } -// Decodes a varint from the current buffer position. -// Returns a status code as described in decoder.int.h. +/* Decodes a varint from the current buffer position. + * Returns a status code as described in decoder.int.h. */ UPB_FORCEINLINE static int32_t decode_varint(upb_pbdecoder *d, uint64_t *u64) { if (curbufleft(d) > 0 && !(*d->ptr & 0x80)) { *u64 = *d->ptr; advance(d, 1); return DECODE_OK; } else if (curbufleft(d) >= 10) { - // Fast case. + /* Fast case. */ upb_decoderet r = upb_vdecode_fast(d->ptr); if (r.p == NULL) { seterr(d, kUnterminatedVarint); @@ -7734,22 +7858,23 @@ UPB_FORCEINLINE static int32_t decode_varint(upb_pbdecoder *d, uint64_t *u64) { *u64 = r.val; return DECODE_OK; } else { - // Slow case -- varint spans buffer seam. + /* Slow case -- varint spans buffer seam. */ return upb_pbdecoder_decode_varint_slow(d, u64); } } -// Decodes a 32-bit varint from the current buffer position. -// Returns a status code as described in decoder.int.h. +/* Decodes a 32-bit varint from the current buffer position. + * Returns a status code as described in decoder.int.h. */ UPB_FORCEINLINE static int32_t decode_v32(upb_pbdecoder *d, uint32_t *u32) { uint64_t u64; int32_t ret = decode_varint(d, &u64); if (ret >= 0) return ret; if (u64 > UINT32_MAX) { seterr(d, "Unterminated 32-bit varint"); - // TODO(haberman) guarantee that this function return is >= 0 somehow, - // so we know this path will always be treated as error by our caller. - // Right now the size_t -> int32_t can overflow and produce negative values. + /* TODO(haberman) guarantee that this function return is >= 0 somehow, + * so we know this path will always be treated as error by our caller. + * Right now the size_t -> int32_t can overflow and produce negative values. + */ *u32 = 0; return upb_pbdecoder_suspend(d); } @@ -7757,22 +7882,22 @@ UPB_FORCEINLINE static int32_t decode_v32(upb_pbdecoder *d, uint32_t *u32) { return DECODE_OK; } -// Decodes a fixed32 from the current buffer position. -// Returns a status code as described in decoder.int.h. -// TODO: proper byte swapping for big-endian machines. +/* Decodes a fixed32 from the current buffer position. + * Returns a status code as described in decoder.int.h. + * TODO: proper byte swapping for big-endian machines. */ UPB_FORCEINLINE static int32_t decode_fixed32(upb_pbdecoder *d, uint32_t *u32) { return getbytes(d, u32, 4); } -// Decodes a fixed64 from the current buffer position. -// Returns a status code as described in decoder.int.h. -// TODO: proper byte swapping for big-endian machines. +/* Decodes a fixed64 from the current buffer position. + * Returns a status code as described in decoder.int.h. + * TODO: proper byte swapping for big-endian machines. */ UPB_FORCEINLINE static int32_t decode_fixed64(upb_pbdecoder *d, uint64_t *u64) { return getbytes(d, u64, 8); } -// Non-static versions of the above functions. -// These are called by the JIT for fallback paths. +/* Non-static versions of the above functions. + * These are called by the JIT for fallback paths. */ int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32) { return decode_fixed32(d, u32); } @@ -7784,7 +7909,7 @@ int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64) { static double as_double(uint64_t n) { double d; memcpy(&d, &n, 8); return d; } static float as_float(uint32_t n) { float f; memcpy(&f, &n, 4); return f; } -// Pushes a frame onto the decoder stack. +/* Pushes a frame onto the decoder stack. */ static bool decoder_push(upb_pbdecoder *d, uint64_t end) { upb_pbdecoder_frame *fr = d->top; @@ -7805,17 +7930,17 @@ static bool decoder_push(upb_pbdecoder *d, uint64_t end) { } static bool pushtagdelim(upb_pbdecoder *d, uint32_t arg) { - // While we expect to see an "end" tag (either ENDGROUP or a non-sequence - // field number) prior to hitting any enclosing submessage end, pushing our - // existing delim end prevents us from continuing to parse values from a - // corrupt proto that doesn't give us an END tag in time. + /* While we expect to see an "end" tag (either ENDGROUP or a non-sequence + * field number) prior to hitting any enclosing submessage end, pushing our + * existing delim end prevents us from continuing to parse values from a + * corrupt proto that doesn't give us an END tag in time. */ if (!decoder_push(d, d->top->end_ofs)) return false; d->top->groupnum = arg; return true; } -// Pops a frame from the decoder stack. +/* Pops a frame from the decoder stack. */ static void decoder_pop(upb_pbdecoder *d) { d->top--; } UPB_NOINLINE int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d, @@ -7824,7 +7949,7 @@ UPB_NOINLINE int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d, size_t bytes = upb_value_size(expected); size_t read = peekbytes(d, &data, bytes); if (read == bytes && data == expected) { - // Advance past matched bytes. + /* Advance past matched bytes. */ int32_t ok = getbytes(d, &data, read); UPB_ASSERT_VAR(ok, ok < 0); return DECODE_OK; @@ -7852,7 +7977,7 @@ have_tag: return upb_pbdecoder_suspend(d); } - // TODO: deliver to unknown field callback. + /* TODO: deliver to unknown field callback. */ switch (wire_type) { case UPB_WIRE_TYPE_32BIT: CHECK_RETURN(skip(d, 4)); @@ -7895,29 +8020,29 @@ have_tag: if (d->ptr == d->delim_end) { seterr(d, "Enclosing submessage ended in the middle of value or group"); - // Unlike most errors we notice during parsing, right now we have consumed - // all of the user's input. - // - // There are three different options for how to handle this case: - // - // 1. decode() = short count, error = set - // 2. decode() = full count, error = set - // 3. decode() = full count, error NOT set, short count and error will - // be reported on next call to decode() (or end()) - // - // (1) and (3) have the advantage that they preserve the invariant that an - // error occurs iff decode() returns a short count. - // - // (2) and (3) have the advantage of reflecting the fact that all of the - // bytes were in fact parsed (and possibly delivered to the unknown field - // handler, in the future when that is supported). - // - // (3) requires extra state in the decode (a place to store the "permanent - // error" that we should return for all subsequent attempts to decode). - // But we likely want this anyway. - // - // Right now we do (1), thanks to the fact that we checkpoint *after* this - // check. (3) may be a better choice long term; unclear at the moment. + /* Unlike most errors we notice during parsing, right now we have consumed + * all of the user's input. + * + * There are three different options for how to handle this case: + * + * 1. decode() = short count, error = set + * 2. decode() = full count, error = set + * 3. decode() = full count, error NOT set, short count and error will + * be reported on next call to decode() (or end()) + * + * (1) and (3) have the advantage that they preserve the invariant that an + * error occurs iff decode() returns a short count. + * + * (2) and (3) have the advantage of reflecting the fact that all of the + * bytes were in fact parsed (and possibly delivered to the unknown field + * handler, in the future when that is supported). + * + * (3) requires extra state in the decode (a place to store the "permanent + * error" that we should return for all subsequent attempts to decode). + * But we likely want this anyway. + * + * Right now we do (1), thanks to the fact that we checkpoint *after* this + * check. (3) may be a better choice long term; unclear at the moment. */ return upb_pbdecoder_suspend(d); } @@ -7932,24 +8057,27 @@ static void goto_endmsg(upb_pbdecoder *d) { d->pc = d->top->base + upb_value_getuint64(v); } -// Parses a tag and jumps to the corresponding bytecode instruction for this -// field. -// -// If the tag is unknown (or the wire type doesn't match), parses the field as -// unknown. If the tag is a valid ENDGROUP tag, jumps to the bytecode -// instruction for the end of message. +/* Parses a tag and jumps to the corresponding bytecode instruction for this + * field. + * + * If the tag is unknown (or the wire type doesn't match), parses the field as + * unknown. If the tag is a valid ENDGROUP tag, jumps to the bytecode + * instruction for the end of message. */ static int32_t dispatch(upb_pbdecoder *d) { upb_inttable *dispatch = d->top->dispatch; - - // Decode tag. uint32_t tag; + uint8_t wire_type; + uint32_t fieldnum; + upb_value val; + int32_t ret; + + /* Decode tag. */ CHECK_RETURN(decode_v32(d, &tag)); - uint8_t wire_type = tag & 0x7; - uint32_t fieldnum = tag >> 3; + wire_type = tag & 0x7; + fieldnum = tag >> 3; - // Lookup tag. Because of packed/non-packed compatibility, we have to - // check the wire type against two possibilities. - upb_value val; + /* Lookup tag. Because of packed/non-packed compatibility, we have to + * check the wire type against two possibilities. */ if (fieldnum != DISPATCH_ENDMSG && upb_inttable_lookup32(dispatch, fieldnum, &val)) { uint64_t v = upb_value_getuint64(val); @@ -7965,17 +8093,17 @@ static int32_t dispatch(upb_pbdecoder *d) { } } - // Unknown field or ENDGROUP. - int32_t ret = upb_pbdecoder_skipunknown(d, fieldnum, wire_type); + /* Unknown field or ENDGROUP. */ + ret = upb_pbdecoder_skipunknown(d, fieldnum, wire_type); if (ret == DECODE_ENDGROUP) { goto_endmsg(d); return DECODE_OK; } else if (ret == DECODE_OK) { - // We just consumed some input, so we might now have consumed all the data - // in the delmited region. Since every opcode that can trigger dispatch is - // directly preceded by OP_CHECKDELIM, rewind to it now to re-check the - // delimited end. + /* We just consumed some input, so we might now have consumed all the data + * in the delmited region. Since every opcode that can trigger dispatch is + * directly preceded by OP_CHECKDELIM, rewind to it now to re-check the + * delimited end. */ d->pc = d->last - 1; assert(getop(*d->pc) == OP_CHECKDELIM); return DECODE_OK; @@ -7984,8 +8112,8 @@ static int32_t dispatch(upb_pbdecoder *d) { return ret; } -// Callers know that the stack is more than one deep because the opcodes that -// call this only occur after PUSH operations. +/* Callers know that the stack is more than one deep because the opcodes that + * call this only occur after PUSH operations. */ upb_pbdecoder_frame *outer_frame(upb_pbdecoder *d) { assert(d->top != d->stack); return d->top - 1; @@ -7994,14 +8122,15 @@ upb_pbdecoder_frame *outer_frame(upb_pbdecoder *d) { /* The main decoding loop *****************************************************/ -// The main decoder VM function. Uses traditional bytecode dispatch loop with a -// switch() statement. +/* The main decoder VM function. Uses traditional bytecode dispatch loop with a + * switch() statement. */ size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf, size_t size, const upb_bufhandle *handle) { upb_pbdecoder *d = closure; const mgroup *group = hd; + int32_t result; assert(buf); - int32_t result = upb_pbdecoder_resume(d, NULL, buf, size, handle); + result = upb_pbdecoder_resume(d, NULL, buf, size, handle); if (result == DECODE_ENDGROUP) { goto_endmsg(d); } @@ -8018,11 +8147,16 @@ size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf, }) while(1) { + int32_t instruction; + opcode op; + uint32_t arg; + int32_t longofs; + d->last = d->pc; - int32_t instruction = *d->pc++; - opcode op = getop(instruction); - uint32_t arg = instruction >> 8; - int32_t longofs = arg; + instruction = *d->pc++; + op = getop(instruction); + arg = instruction >> 8; + longofs = arg; assert(d->ptr != d->residual_end); #ifdef UPB_DUMP_BYTECODE fprintf(stderr, "s_ofs=%d buf_ofs=%d data_rem=%d buf_rem=%d delim_rem=%d " @@ -8037,9 +8171,9 @@ size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf, arg); #endif switch (op) { - // Technically, we are losing data if we see a 32-bit varint that is not - // properly sign-extended. We could detect this and error about the data - // loss, but proto2 does not do this, so we pass. + /* Technically, we are losing data if we see a 32-bit varint that is not + * properly sign-extended. We could detect this and error about the data + * loss, but proto2 does not do this, so we pass. */ PRIMITIVE_OP(INT32, varint, int32, int32_t, uint64_t) PRIMITIVE_OP(INT64, varint, int64, int64_t, uint64_t) PRIMITIVE_OP(UINT32, varint, uint32, uint32_t, uint64_t) @@ -8084,7 +8218,7 @@ size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf, upb_pbdecoder_frame *outer = outer_frame(d); CHECK_SUSPEND(upb_sink_startstr(&outer->sink, arg, len, &d->top->sink)); if (len == 0) { - d->pc++; // Skip OP_STRING. + d->pc++; /* Skip OP_STRING. */ } ) VMCASE(OP_STRING, @@ -8096,15 +8230,15 @@ size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf, return upb_pbdecoder_suspend(d); } else { int32_t ret = skip(d, n); - // This shouldn't return DECODE_OK, because n > len. + /* This shouldn't return DECODE_OK, because n > len. */ assert(ret >= 0); return ret; } } advance(d, n); if (n < len || d->delim_end == NULL) { - // We aren't finished with this string yet. - d->pc--; // Repeat OP_STRING. + /* We aren't finished with this string yet. */ + d->pc--; /* Repeat OP_STRING. */ if (n > 0) checkpoint(d); return upb_pbdecoder_suspend(d); } @@ -8132,8 +8266,9 @@ size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf, set_delim_end(d); ) VMCASE(OP_CHECKDELIM, - // We are guaranteed of this assert because we never allow ourselves to - // consume bytes beyond data_end, which covers delim_end when non-NULL. + /* We are guaranteed of this assert because we never allow ourselves to + * consume bytes beyond data_end, which covers delim_end when non-NULL. + */ assert(!(d->delim_end && d->ptr > d->delim_end)); if (d->ptr == d->delim_end) d->pc += longofs; @@ -8150,8 +8285,9 @@ size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf, d->pc += longofs; ) VMCASE(OP_TAG1, + uint8_t expected; CHECK_SUSPEND(curbufleft(d) > 0); - uint8_t expected = (arg >> 8) & 0xff; + expected = (arg >> 8) & 0xff; if (*d->ptr == expected) { advance(d, 1); } else { @@ -8162,13 +8298,14 @@ size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf, CHECK_RETURN(dispatch(d)); } else { d->pc += shortofs; - break; // Avoid checkpoint(). + break; /* Avoid checkpoint(). */ } } ) VMCASE(OP_TAG2, + uint16_t expected; CHECK_SUSPEND(curbufleft(d) > 0); - uint16_t expected = (arg >> 8) & 0xffff; + expected = (arg >> 8) & 0xffff; if (curbufleft(d) >= 2) { uint16_t actual; memcpy(&actual, d->ptr, 2); @@ -8185,9 +8322,10 @@ size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf, ) VMCASE(OP_TAGN, { uint64_t expected; + int32_t result; memcpy(&expected, d->pc, 8); d->pc += 2; - int32_t result = upb_pbdecoder_checktag_slow(d, expected); + result = upb_pbdecoder_checktag_slow(d, expected); if (result == DECODE_MISMATCH) goto badtag; if (result >= 0) return result; }) @@ -8213,9 +8351,9 @@ void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint) { } void *upb_pbdecoder_startjit(void *closure, const void *hd, size_t size_hint) { + upb_pbdecoder *d = closure; UPB_UNUSED(hd); UPB_UNUSED(size_hint); - upb_pbdecoder *d = closure; d->top->end_ofs = UINT64_MAX; d->bufstart_ofs = 0; d->call_len = 0; @@ -8225,6 +8363,11 @@ void *upb_pbdecoder_startjit(void *closure, const void *hd, size_t size_hint) { bool upb_pbdecoder_end(void *closure, const void *handler_data) { upb_pbdecoder *d = closure; const upb_pbdecodermethod *method = handler_data; + uint64_t end; + char dummy; +#ifdef UPB_USE_JIT_X64 + const mgroup *group = (const mgroup*)method->group; +#endif if (d->residual_end > d->residual) { seterr(d, "Unexpected EOF"); @@ -8236,35 +8379,32 @@ bool upb_pbdecoder_end(void *closure, const void *handler_data) { return false; } - // Message ends here. - uint64_t end = offset(d); + /* Message ends here. */ + end = offset(d); d->top->end_ofs = end; - char dummy; #ifdef UPB_USE_JIT_X64 - const mgroup *group = (const mgroup*)method->group; if (group->jit_code) { if (d->top != d->stack) d->stack->end_ofs = 0; group->jit_code(closure, method->code_base.ptr, &dummy, 0, NULL); - } else { + } else #endif - d->stack->end_ofs = end; + { const uint32_t *p = d->pc; - // Check the previous bytecode, but guard against beginning. + d->stack->end_ofs = end; + /* Check the previous bytecode, but guard against beginning. */ if (p != method->code_base.ptr) p--; if (getop(*p) == OP_CHECKDELIM) { - // Rewind from OP_TAG* to OP_CHECKDELIM. + /* Rewind from OP_TAG* to OP_CHECKDELIM. */ assert(getop(*d->pc) == OP_TAG1 || getop(*d->pc) == OP_TAG2 || getop(*d->pc) == OP_TAGN || - getop(*d->pc == OP_DISPATCH)); + getop(*d->pc) == OP_DISPATCH); d->pc = p; } upb_pbdecoder_decode(closure, handler_data, &dummy, 0, NULL); -#ifdef UPB_USE_JIT_X64 } -#endif if (d->call_len != 0) { seterr(d, "Unexpected EOF"); @@ -8293,8 +8433,8 @@ static size_t callstacksize(upb_pbdecoder *d, size_t entries) { #ifdef UPB_USE_JIT_X64 if (d->method_->is_native_) { - // Each native stack frame needs two pointers, plus we need a few frames for - // the enter/exit trampolines. + /* Each native stack frame needs two pointers, plus we need a few frames for + * the enter/exit trampolines. */ size_t ret = entries * sizeof(void*) * 2; ret += sizeof(void*) * 10; return ret; @@ -8335,7 +8475,7 @@ upb_pbdecoder *upb_pbdecoder_create(upb_env *e, const upb_pbdecodermethod *m, } upb_sink_reset(&d->top->sink, sink->handlers, sink->closure); - // If this fails, increase the value in decoder.h. + /* If this fails, increase the value in decoder.h. */ assert(upb_env_bytesallocated(e) - size_before <= UPB_PB_DECODER_SIZE); return d; } @@ -8360,12 +8500,12 @@ bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) { assert(d->top >= d->stack); if (max < (size_t)(d->top - d->stack)) { - // Can't set a limit smaller than what we are currently at. + /* Can't set a limit smaller than what we are currently at. */ return false; } if (max > d->stack_size) { - // Need to reallocate stack and callstack to accommodate. + /* Need to reallocate stack and callstack to accommodate. */ size_t old_size = stacksize(d, d->stack_size); size_t new_size = stacksize(d, max); void *p = upb_env_realloc(d->env, d->stack, old_size, new_size); @@ -8450,73 +8590,74 @@ bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) { #include <stdlib.h> -// The output buffer is divided into segments; a segment is a string of data -// that is "ready to go" -- it does not need any varint lengths inserted into -// the middle. The seams between segments are where varints will be inserted -// once they are known. -// -// We also use the concept of a "run", which is a range of encoded bytes that -// occur at a single submessage level. Every segment contains one or more runs. -// -// A segment can span messages. Consider: -// -// .--Submessage lengths---------. -// | | | -// | V V -// V | |--------------- | |----------------- -// Submessages: | |----------------------------------------------- -// Top-level msg: ------------------------------------------------------------ -// -// Segments: ----- ------------------- ----------------- -// Runs: *---- *--------------*--- *---------------- -// (* marks the start) -// -// Note that the top-level menssage is not in any segment because it does not -// have any length preceding it. -// -// A segment is only interrupted when another length needs to be inserted. So -// observe how the second segment spans both the inner submessage and part of -// the next enclosing message. +/* The output buffer is divided into segments; a segment is a string of data + * that is "ready to go" -- it does not need any varint lengths inserted into + * the middle. The seams between segments are where varints will be inserted + * once they are known. + * + * We also use the concept of a "run", which is a range of encoded bytes that + * occur at a single submessage level. Every segment contains one or more runs. + * + * A segment can span messages. Consider: + * + * .--Submessage lengths---------. + * | | | + * | V V + * V | |--------------- | |----------------- + * Submessages: | |----------------------------------------------- + * Top-level msg: ------------------------------------------------------------ + * + * Segments: ----- ------------------- ----------------- + * Runs: *---- *--------------*--- *---------------- + * (* marks the start) + * + * Note that the top-level menssage is not in any segment because it does not + * have any length preceding it. + * + * A segment is only interrupted when another length needs to be inserted. So + * observe how the second segment spans both the inner submessage and part of + * the next enclosing message. */ typedef struct { - uint32_t msglen; // The length to varint-encode before this segment. - uint32_t seglen; // Length of the segment. + uint32_t msglen; /* The length to varint-encode before this segment. */ + uint32_t seglen; /* Length of the segment. */ } upb_pb_encoder_segment; struct upb_pb_encoder { upb_env *env; - // Our input and output. + /* Our input and output. */ upb_sink input_; upb_bytessink *output_; - // The "subclosure" -- used as the inner closure as part of the bytessink - // protocol. + /* The "subclosure" -- used as the inner closure as part of the bytessink + * protocol. */ void *subc; - // The output buffer and limit, and our current write position. "buf" - // initially points to "initbuf", but is dynamically allocated if we need to - // grow beyond the initial size. + /* The output buffer and limit, and our current write position. "buf" + * initially points to "initbuf", but is dynamically allocated if we need to + * grow beyond the initial size. */ char *buf, *ptr, *limit; - // The beginning of the current run, or undefined if we are at the top level. + /* The beginning of the current run, or undefined if we are at the top + * level. */ char *runbegin; - // The list of segments we are accumulating. + /* The list of segments we are accumulating. */ upb_pb_encoder_segment *segbuf, *segptr, *seglimit; - // The stack of enclosing submessages. Each entry in the stack points to the - // segment where this submessage's length is being accumulated. + /* The stack of enclosing submessages. Each entry in the stack points to the + * segment where this submessage's length is being accumulated. */ int *stack, *top, *stacklimit; - // Depth of startmsg/endmsg calls. + /* Depth of startmsg/endmsg calls. */ int depth; }; /* low-level buffering ********************************************************/ -// Low-level functions for interacting with the output buffer. +/* Low-level functions for interacting with the output buffer. */ -// TODO(haberman): handle pushback +/* TODO(haberman): handle pushback */ static void putbuf(upb_pb_encoder *e, const char *buf, size_t len) { size_t n = upb_bytessink_putbuf(e->output_, e->subc, buf, len, NULL); UPB_ASSERT_VAR(n, n == len); @@ -8526,11 +8667,12 @@ static upb_pb_encoder_segment *top(upb_pb_encoder *e) { return &e->segbuf[*e->top]; } -// Call to ensure that at least "bytes" bytes are available for writing at -// e->ptr. Returns false if the bytes could not be allocated. +/* Call to ensure that at least "bytes" bytes are available for writing at + * e->ptr. Returns false if the bytes could not be allocated. */ static bool reserve(upb_pb_encoder *e, size_t bytes) { if ((size_t)(e->limit - e->ptr) < bytes) { - // Grow buffer. + /* Grow buffer. */ + char *new_buf; size_t needed = bytes + (e->ptr - e->buf); size_t old_size = e->limit - e->buf; @@ -8540,7 +8682,7 @@ static bool reserve(upb_pb_encoder *e, size_t bytes) { new_size *= 2; } - char *new_buf = upb_env_realloc(e->env, e->buf, old_size, new_size); + new_buf = upb_env_realloc(e->env, e->buf, old_size, new_size); if (new_buf == NULL) { return false; @@ -8555,22 +8697,22 @@ static bool reserve(upb_pb_encoder *e, size_t bytes) { return true; } -// Call when "bytes" bytes have been writte at e->ptr. The caller *must* have -// previously called reserve() with at least this many bytes. +/* Call when "bytes" bytes have been writte at e->ptr. The caller *must* have + * previously called reserve() with at least this many bytes. */ static void encoder_advance(upb_pb_encoder *e, size_t bytes) { assert((size_t)(e->limit - e->ptr) >= bytes); e->ptr += bytes; } -// Call when all of the bytes for a handler have been written. Flushes the -// bytes if possible and necessary, returning false if this failed. +/* Call when all of the bytes for a handler have been written. Flushes the + * bytes if possible and necessary, returning false if this failed. */ static bool commit(upb_pb_encoder *e) { if (!e->top) { - // We aren't inside a delimited region. Flush our accumulated bytes to - // the output. - // - // TODO(haberman): in the future we may want to delay flushing for - // efficiency reasons. + /* We aren't inside a delimited region. Flush our accumulated bytes to + * the output. + * + * TODO(haberman): in the future we may want to delay flushing for + * efficiency reasons. */ putbuf(e, e->buf, e->ptr - e->buf); e->ptr = e->buf; } @@ -8578,7 +8720,7 @@ static bool commit(upb_pb_encoder *e) { return true; } -// Writes the given bytes to the buffer, handling reserve/advance. +/* Writes the given bytes to the buffer, handling reserve/advance. */ static bool encode_bytes(upb_pb_encoder *e, const void *data, size_t len) { if (!reserve(e, len)) { return false; @@ -8589,32 +8731,33 @@ static bool encode_bytes(upb_pb_encoder *e, const void *data, size_t len) { return true; } -// Finish the current run by adding the run totals to the segment and message -// length. +/* Finish the current run by adding the run totals to the segment and message + * length. */ static void accumulate(upb_pb_encoder *e) { + size_t run_len; assert(e->ptr >= e->runbegin); - size_t run_len = e->ptr - e->runbegin; + run_len = e->ptr - e->runbegin; e->segptr->seglen += run_len; top(e)->msglen += run_len; e->runbegin = e->ptr; } -// Call to indicate the start of delimited region for which the full length is -// not yet known. All data will be buffered until the length is known. -// Delimited regions may be nested; their lengths will all be tracked properly. +/* Call to indicate the start of delimited region for which the full length is + * not yet known. All data will be buffered until the length is known. + * Delimited regions may be nested; their lengths will all be tracked properly. */ static bool start_delim(upb_pb_encoder *e) { if (e->top) { - // We are already buffering, advance to the next segment and push it on the - // stack. + /* We are already buffering, advance to the next segment and push it on the + * stack. */ accumulate(e); if (++e->top == e->stacklimit) { - // TODO(haberman): grow stack? + /* TODO(haberman): grow stack? */ return false; } if (++e->segptr == e->seglimit) { - // Grow segment buffer. + /* Grow segment buffer. */ size_t old_size = (e->seglimit - e->segbuf) * sizeof(upb_pb_encoder_segment); size_t new_size = old_size * 2; @@ -8630,7 +8773,7 @@ static bool start_delim(upb_pb_encoder *e) { e->segbuf = new_buf; } } else { - // We were previously at the top level, start buffering. + /* We were previously at the top level, start buffering. */ e->segptr = e->segbuf; e->top = e->stack; e->runbegin = e->ptr; @@ -8643,15 +8786,16 @@ static bool start_delim(upb_pb_encoder *e) { return true; } -// Call to indicate the end of a delimited region. We now know the length of -// the delimited region. If we are not nested inside any other delimited -// regions, we can now emit all of the buffered data we accumulated. +/* Call to indicate the end of a delimited region. We now know the length of + * the delimited region. If we are not nested inside any other delimited + * regions, we can now emit all of the buffered data we accumulated. */ static bool end_delim(upb_pb_encoder *e) { + size_t msglen; accumulate(e); - size_t msglen = top(e)->msglen; + msglen = top(e)->msglen; if (e->top == e->stack) { - // All lengths are now available, emit all buffered data. + /* All lengths are now available, emit all buffered data. */ char buf[UPB_PB_VARINT_MAX_LEN]; upb_pb_encoder_segment *s; const char *ptr = e->buf; @@ -8665,7 +8809,8 @@ static bool end_delim(upb_pb_encoder *e) { e->ptr = e->buf; e->top = NULL; } else { - // Need to keep buffering; propagate length info into enclosing submessages. + /* Need to keep buffering; propagate length info into enclosing + * submessages. */ --e->top; top(e)->msglen += msglen + upb_varint_size(msglen); } @@ -8676,14 +8821,14 @@ static bool end_delim(upb_pb_encoder *e) { /* tag_t **********************************************************************/ -// A precomputed (pre-encoded) tag and length. +/* A precomputed (pre-encoded) tag and length. */ typedef struct { uint8_t bytes; char tag[7]; } tag_t; -// Allocates a new tag for this field, and sets it in these handlerattr. +/* Allocates a new tag for this field, and sets it in these handlerattr. */ static void new_tag(upb_handlers *h, const upb_fielddef *f, upb_wiretype_t wt, upb_handlerattr *attr) { uint32_t n = upb_fielddef_number(f); @@ -8704,12 +8849,12 @@ static bool encode_tag(upb_pb_encoder *e, const tag_t *tag) { /* encoding of wire types *****************************************************/ static bool encode_fixed64(upb_pb_encoder *e, uint64_t val) { - // TODO(haberman): byte-swap for big endian. + /* TODO(haberman): byte-swap for big endian. */ return encode_bytes(e, &val, sizeof(uint64_t)); } static bool encode_fixed32(upb_pb_encoder *e, uint32_t val) { - // TODO(haberman): byte-swap for big endian. + /* TODO(haberman): byte-swap for big endian. */ return encode_bytes(e, &val, sizeof(uint32_t)); } @@ -8796,19 +8941,19 @@ static size_t encode_strbuf(void *c, const void *hd, const char *buf, } T(double, double, dbl2uint64, encode_fixed64) -T(float, float, flt2uint32, encode_fixed32); -T(int64, int64_t, uint64_t, encode_varint); -T(int32, int32_t, uint32_t, encode_varint); -T(fixed64, uint64_t, uint64_t, encode_fixed64); -T(fixed32, uint32_t, uint32_t, encode_fixed32); -T(bool, bool, bool, encode_varint); -T(uint32, uint32_t, uint32_t, encode_varint); -T(uint64, uint64_t, uint64_t, encode_varint); -T(enum, int32_t, uint32_t, encode_varint); -T(sfixed32, int32_t, uint32_t, encode_fixed32); -T(sfixed64, int64_t, uint64_t, encode_fixed64); -T(sint32, int32_t, upb_zzenc_32, encode_varint); -T(sint64, int64_t, upb_zzenc_64, encode_varint); +T(float, float, flt2uint32, encode_fixed32) +T(int64, int64_t, uint64_t, encode_varint) +T(int32, int32_t, uint32_t, encode_varint) +T(fixed64, uint64_t, uint64_t, encode_fixed64) +T(fixed32, uint32_t, uint32_t, encode_fixed32) +T(bool, bool, bool, encode_varint) +T(uint32, uint32_t, uint32_t, encode_varint) +T(uint64, uint64_t, uint64_t, encode_varint) +T(enum, int32_t, uint32_t, encode_varint) +T(sfixed32, int32_t, uint32_t, encode_fixed32) +T(sfixed64, int64_t, uint64_t, encode_fixed64) +T(sint32, int32_t, upb_zzenc_32, encode_varint) +T(sint64, int64_t, upb_zzenc_64, encode_varint) #undef T @@ -8816,13 +8961,15 @@ T(sint64, int64_t, upb_zzenc_64, encode_varint); /* code to build the handlers *************************************************/ static void newhandlers_callback(const void *closure, upb_handlers *h) { + const upb_msgdef *m; + upb_msg_field_iter i; + UPB_UNUSED(closure); upb_handlers_setstartmsg(h, startmsg, NULL); upb_handlers_setendmsg(h, endmsg, NULL); - const upb_msgdef *m = upb_handlers_msgdef(h); - upb_msg_field_iter i; + m = upb_handlers_msgdef(h); for(upb_msg_field_begin(&i, m); !upb_msg_field_done(&i); upb_msg_field_next(&i)) { @@ -8834,7 +8981,7 @@ static void newhandlers_callback(const void *closure, upb_handlers *h) { packed ? UPB_WIRE_TYPE_DELIMITED : upb_pb_native_wire_types[upb_fielddef_descriptortype(f)]; - // Pre-encode the tag for this field. + /* Pre-encode the tag for this field. */ new_tag(h, f, wt, &attr); if (packed) { @@ -8877,7 +9024,7 @@ static void newhandlers_callback(const void *closure, upb_handlers *h) { upb_handlers_setendsubmsg(h, f, encode_enddelimfield, &attr); break; case UPB_DESCRIPTOR_TYPE_GROUP: { - // Endgroup takes a different tag (wire_type = END_GROUP). + /* Endgroup takes a different tag (wire_type = END_GROUP). */ upb_handlerattr attr2; new_tag(h, f, UPB_WIRE_TYPE_END_GROUP, &attr2); @@ -8913,7 +9060,7 @@ upb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h, upb_bytessink *output) { const size_t initial_bufsize = 256; const size_t initial_segbufsize = 16; - // TODO(haberman): make this configurable. + /* TODO(haberman): make this configurable. */ const size_t stack_size = 64; #ifndef NDEBUG const size_t size_before = upb_env_bytesallocated(env); @@ -8942,7 +9089,7 @@ upb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h, e->subc = output->closure; e->ptr = e->buf; - // If this fails, increase the value in encoder.h. + /* If this fails, increase the value in encoder.h. */ assert(upb_env_bytesallocated(env) - size_before <= UPB_PB_ENCODER_SIZE); return e; } @@ -8962,28 +9109,31 @@ upb_sink *upb_pb_encoder_input(upb_pb_encoder *e) { return &e->input_; } upb_def **upb_load_defs_from_descriptor(const char *str, size_t len, int *n, void *owner, upb_status *status) { - // Create handlers. + /* Create handlers. */ + const upb_pbdecodermethod *decoder_m; const upb_handlers *reader_h = upb_descreader_newhandlers(&reader_h); + upb_env env; upb_pbdecodermethodopts opts; + upb_pbdecoder *decoder; + upb_descreader *reader; + bool ok; + upb_def **ret = NULL; + upb_def **defs; + upb_pbdecodermethodopts_init(&opts, reader_h); - const upb_pbdecodermethod *decoder_m = - upb_pbdecodermethod_new(&opts, &decoder_m); + decoder_m = upb_pbdecodermethod_new(&opts, &decoder_m); - upb_env env; upb_env_init(&env); upb_env_reporterrorsto(&env, status); - upb_descreader *reader = upb_descreader_create(&env, reader_h); - upb_pbdecoder *decoder = - upb_pbdecoder_create(&env, decoder_m, upb_descreader_input(reader)); - - // Push input data. - bool ok = upb_bufsrc_putbuf(str, len, upb_pbdecoder_input(decoder)); + reader = upb_descreader_create(&env, reader_h); + decoder = upb_pbdecoder_create(&env, decoder_m, upb_descreader_input(reader)); - upb_def **ret = NULL; + /* Push input data. */ + ok = upb_bufsrc_putbuf(str, len, upb_pbdecoder_input(decoder)); if (!ok) goto cleanup; - upb_def **defs = upb_descreader_getdefs(reader, owner, n); + defs = upb_descreader_getdefs(reader, owner, n); ret = malloc(sizeof(upb_def*) * (*n)); memcpy(ret, defs, sizeof(upb_def*) * (*n)); @@ -8997,21 +9147,24 @@ cleanup: bool upb_load_descriptor_into_symtab(upb_symtab *s, const char *str, size_t len, upb_status *status) { int n; + bool success; upb_def **defs = upb_load_defs_from_descriptor(str, len, &n, &defs, status); if (!defs) return false; - bool success = upb_symtab_add(s, defs, n, &defs, status); + success = upb_symtab_add(s, defs, n, &defs, status); free(defs); return success; } char *upb_readfile(const char *filename, size_t *len) { + long size; + char *buf; FILE *f = fopen(filename, "rb"); if(!f) return NULL; if(fseek(f, 0, SEEK_END) != 0) goto error; - long size = ftell(f); + size = ftell(f); if(size < 0) goto error; if(fseek(f, 0, SEEK_SET) != 0) goto error; - char *buf = malloc(size + 1); + buf = malloc(size + 1); if(size && fread(buf, size, 1, f) != 1) goto error; fclose(f); if (len) *len = size; @@ -9025,12 +9178,13 @@ error: bool upb_load_descriptor_file_into_symtab(upb_symtab *symtab, const char *fname, upb_status *status) { size_t len; + bool success; char *data = upb_readfile(fname, &len); if (!data) { if (status) upb_status_seterrf(status, "Couldn't read file: %s", fname); return false; } - bool success = upb_load_descriptor_into_symtab(symtab, data, len, status); + success = upb_load_descriptor_into_symtab(symtab, data, len, status); free(data); return success; } @@ -9048,6 +9202,7 @@ bool upb_load_descriptor_file_into_symtab(upb_symtab *symtab, const char *fname, #include <ctype.h> #include <float.h> #include <inttypes.h> +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -9084,22 +9239,24 @@ static int endfield(upb_textprinter *p) { static int putescaped(upb_textprinter *p, const char *buf, size_t len, bool preserve_utf8) { - // Based on CEscapeInternal() from Google's protobuf release. + /* Based on CEscapeInternal() from Google's protobuf release. */ char dstbuf[4096], *dst = dstbuf, *dstend = dstbuf + sizeof(dstbuf); const char *end = buf + len; - // I think hex is prettier and more useful, but proto2 uses octal; should - // investigate whether it can parse hex also. + /* I think hex is prettier and more useful, but proto2 uses octal; should + * investigate whether it can parse hex also. */ const bool use_hex = false; - bool last_hex_escape = false; // true if last output char was \xNN + bool last_hex_escape = false; /* true if last output char was \xNN */ for (; buf < end; buf++) { + bool is_hex_escape; + if (dstend - dst < 4) { upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL); dst = dstbuf; } - bool is_hex_escape = false; + is_hex_escape = false; switch (*buf) { case '\n': *(dst++) = '\\'; *(dst++) = 'n'; break; case '\r': *(dst++) = '\\'; *(dst++) = 'r'; break; @@ -9108,9 +9265,9 @@ static int putescaped(upb_textprinter *p, const char *buf, size_t len, case '\'': *(dst++) = '\\'; *(dst++) = '\''; break; case '\\': *(dst++) = '\\'; *(dst++) = '\\'; break; default: - // Note that if we emit \xNN and the buf character after that is a hex - // digit then that digit must be escaped too to prevent it being - // interpreted as part of the character code by C. + /* Note that if we emit \xNN and the buf character after that is a hex + * digit then that digit must be escaped too to prevent it being + * interpreted as part of the character code by C. */ if ((!preserve_utf8 || (uint8_t)*buf < 0x80) && (!isprint(*buf) || (last_hex_escape && isxdigit(*buf)))) { sprintf(dst, (use_hex ? "\\x%02x" : "\\%03o"), (uint8_t)*buf); @@ -9122,29 +9279,34 @@ static int putescaped(upb_textprinter *p, const char *buf, size_t len, } last_hex_escape = is_hex_escape; } - // Flush remaining data. + /* Flush remaining data. */ upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL); return 0; } bool putf(upb_textprinter *p, const char *fmt, ...) { va_list args; + va_list args_copy; + char *str; + int written; + int len; + bool ok; + va_start(args, fmt); - // Run once to get the length of the string. - va_list args_copy; - va_copy(args_copy, args); - int len = vsnprintf(NULL, 0, fmt, args_copy); + /* Run once to get the length of the string. */ + _upb_va_copy(args_copy, args); + len = _upb_vsnprintf(NULL, 0, fmt, args_copy); va_end(args_copy); - // + 1 for NULL terminator (vsnprintf() requires it even if we don't). - char *str = malloc(len + 1); + /* + 1 for NULL terminator (vsprintf() requires it even if we don't). */ + str = malloc(len + 1); if (!str) return false; - int written = vsnprintf(str, len + 1, fmt, args); + written = vsprintf(str, fmt, args); va_end(args); UPB_ASSERT_VAR(written, written == len); - bool ok = upb_bytessink_putbuf(p->output_, p->subc, str, len, NULL); + ok = upb_bytessink_putbuf(p->output_, p->subc, str, len, NULL); free(str); return ok; } @@ -9153,8 +9315,8 @@ bool putf(upb_textprinter *p, const char *fmt, ...) { /* handlers *******************************************************************/ static bool textprinter_startmsg(void *c, const void *hd) { - UPB_UNUSED(hd); upb_textprinter *p = c; + UPB_UNUSED(hd); if (p->indent_depth_ == 0) { upb_bytessink_start(p->output_, 0, &p->subc); } @@ -9162,9 +9324,9 @@ static bool textprinter_startmsg(void *c, const void *hd) { } static bool textprinter_endmsg(void *c, const void *hd, upb_status *s) { + upb_textprinter *p = c; UPB_UNUSED(hd); UPB_UNUSED(s); - upb_textprinter *p = c; if (p->indent_depth_ == 0) { upb_bytessink_end(p->output_); } @@ -9201,14 +9363,14 @@ err: TYPE(int32, int32_t, "%" PRId32) TYPE(int64, int64_t, "%" PRId64) -TYPE(uint32, uint32_t, "%" PRIu32); +TYPE(uint32, uint32_t, "%" PRIu32) TYPE(uint64, uint64_t, "%" PRIu64) TYPE(float, float, "%." STRINGIFY_MACROVAL(FLT_DIG) "g") TYPE(double, double, "%." STRINGIFY_MACROVAL(DBL_DIG) "g") #undef TYPE -// Output a symbolic value from the enum if found, else just print as int32. +/* Output a symbolic value from the enum if found, else just print as int32. */ static bool textprinter_putenum(void *closure, const void *handler_data, int32_t val) { upb_textprinter *p = closure; @@ -9228,17 +9390,17 @@ static bool textprinter_putenum(void *closure, const void *handler_data, static void *textprinter_startstr(void *closure, const void *handler_data, size_t size_hint) { + upb_textprinter *p = closure; const upb_fielddef *f = handler_data; UPB_UNUSED(size_hint); - upb_textprinter *p = closure; indent(p); putf(p, "%s: \"", upb_fielddef_name(f)); return p; } static bool textprinter_endstr(void *closure, const void *handler_data) { - UPB_UNUSED(handler_data); upb_textprinter *p = closure; + UPB_UNUSED(handler_data); putf(p, "\""); endfield(p); return true; @@ -9246,9 +9408,9 @@ static bool textprinter_endstr(void *closure, const void *handler_data) { static size_t textprinter_putstr(void *closure, const void *hd, const char *buf, size_t len, const upb_bufhandle *handle) { - UPB_UNUSED(handle); upb_textprinter *p = closure; const upb_fielddef *f = hd; + UPB_UNUSED(handle); CHECK(putescaped(p, buf, len, upb_fielddef_type(f) == UPB_TYPE_STRING)); return len; err: @@ -9267,8 +9429,8 @@ err: } static bool textprinter_endsubmsg(void *closure, const void *handler_data) { - UPB_UNUSED(handler_data); upb_textprinter *p = closure; + UPB_UNUSED(handler_data); p->indent_depth_--; CHECK(indent(p)); upb_bytessink_putbuf(p->output_, p->subc, "}", 1, NULL); @@ -9279,13 +9441,13 @@ err: } static void onmreg(const void *c, upb_handlers *h) { - UPB_UNUSED(c); const upb_msgdef *m = upb_handlers_msgdef(h); + upb_msg_field_iter i; + UPB_UNUSED(c); upb_handlers_setstartmsg(h, textprinter_startmsg, NULL); upb_handlers_setendmsg(h, textprinter_endmsg, NULL); - upb_msg_field_iter i; for(upb_msg_field_begin(&i, m); !upb_msg_field_done(&i); upb_msg_field_next(&i)) { @@ -9375,32 +9537,33 @@ void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line) { */ -// Index is descriptor type. +/* Index is descriptor type. */ const uint8_t upb_pb_native_wire_types[] = { - UPB_WIRE_TYPE_END_GROUP, // ENDGROUP - UPB_WIRE_TYPE_64BIT, // DOUBLE - UPB_WIRE_TYPE_32BIT, // FLOAT - UPB_WIRE_TYPE_VARINT, // INT64 - UPB_WIRE_TYPE_VARINT, // UINT64 - UPB_WIRE_TYPE_VARINT, // INT32 - UPB_WIRE_TYPE_64BIT, // FIXED64 - UPB_WIRE_TYPE_32BIT, // FIXED32 - UPB_WIRE_TYPE_VARINT, // BOOL - UPB_WIRE_TYPE_DELIMITED, // STRING - UPB_WIRE_TYPE_START_GROUP, // GROUP - UPB_WIRE_TYPE_DELIMITED, // MESSAGE - UPB_WIRE_TYPE_DELIMITED, // BYTES - UPB_WIRE_TYPE_VARINT, // UINT32 - UPB_WIRE_TYPE_VARINT, // ENUM - UPB_WIRE_TYPE_32BIT, // SFIXED32 - UPB_WIRE_TYPE_64BIT, // SFIXED64 - UPB_WIRE_TYPE_VARINT, // SINT32 - UPB_WIRE_TYPE_VARINT, // SINT64 + UPB_WIRE_TYPE_END_GROUP, /* ENDGROUP */ + UPB_WIRE_TYPE_64BIT, /* DOUBLE */ + UPB_WIRE_TYPE_32BIT, /* FLOAT */ + UPB_WIRE_TYPE_VARINT, /* INT64 */ + UPB_WIRE_TYPE_VARINT, /* UINT64 */ + UPB_WIRE_TYPE_VARINT, /* INT32 */ + UPB_WIRE_TYPE_64BIT, /* FIXED64 */ + UPB_WIRE_TYPE_32BIT, /* FIXED32 */ + UPB_WIRE_TYPE_VARINT, /* BOOL */ + UPB_WIRE_TYPE_DELIMITED, /* STRING */ + UPB_WIRE_TYPE_START_GROUP, /* GROUP */ + UPB_WIRE_TYPE_DELIMITED, /* MESSAGE */ + UPB_WIRE_TYPE_DELIMITED, /* BYTES */ + UPB_WIRE_TYPE_VARINT, /* UINT32 */ + UPB_WIRE_TYPE_VARINT, /* ENUM */ + UPB_WIRE_TYPE_32BIT, /* SFIXED32 */ + UPB_WIRE_TYPE_64BIT, /* SFIXED64 */ + UPB_WIRE_TYPE_VARINT, /* SINT32 */ + UPB_WIRE_TYPE_VARINT, /* SINT64 */ }; -// A basic branch-based decoder, uses 32-bit values to get good performance -// on 32-bit architectures (but performs well on 64-bits also). -// This scheme comes from the original Google Protobuf implementation (proto2). +/* A basic branch-based decoder, uses 32-bit values to get good performance + * on 32-bit architectures (but performs well on 64-bits also). + * This scheme comes from the original Google Protobuf implementation + * (proto2). */ upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r) { upb_decoderet err = {NULL, 0}; const char *p = r.p; @@ -9424,7 +9587,7 @@ done: return r; } -// Like the previous, but uses 64-bit values. +/* Like the previous, but uses 64-bit values. */ upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r) { const char *p = r.p; uint64_t val = r.val; @@ -9446,50 +9609,54 @@ done: return r; } -// Given an encoded varint v, returns an integer with a single bit set that -// indicates the end of the varint. Subtracting one from this value will -// yield a mask that leaves only bits that are part of the varint. Returns -// 0 if the varint is unterminated. +/* Given an encoded varint v, returns an integer with a single bit set that + * indicates the end of the varint. Subtracting one from this value will + * yield a mask that leaves only bits that are part of the varint. Returns + * 0 if the varint is unterminated. */ static uint64_t upb_get_vstopbit(uint64_t v) { uint64_t cbits = v | 0x7f7f7f7f7f7f7f7fULL; return ~cbits & (cbits+1); } -// A branchless decoder. Credit to Pascal Massimino for the bit-twiddling. +/* A branchless decoder. Credit to Pascal Massimino for the bit-twiddling. */ upb_decoderet upb_vdecode_max8_massimino(upb_decoderet r) { uint64_t b; + uint64_t stop_bit; + upb_decoderet my_r; memcpy(&b, r.p, sizeof(b)); - uint64_t stop_bit = upb_get_vstopbit(b); + stop_bit = upb_get_vstopbit(b); b = (b & 0x7f7f7f7f7f7f7f7fULL) & (stop_bit - 1); b += b & 0x007f007f007f007fULL; b += 3 * (b & 0x0000ffff0000ffffULL); b += 15 * (b & 0x00000000ffffffffULL); if (stop_bit == 0) { - // Error: unterminated varint. + /* Error: unterminated varint. */ upb_decoderet err_r = {(void*)0, 0}; return err_r; } - upb_decoderet my_r = {r.p + ((__builtin_ctzll(stop_bit) + 1) / 8), - r.val | (b << 7)}; + my_r = upb_decoderet_make(r.p + ((__builtin_ctzll(stop_bit) + 1) / 8), + r.val | (b << 7)); return my_r; } -// A branchless decoder. Credit to Daniel Wright for the bit-twiddling. +/* A branchless decoder. Credit to Daniel Wright for the bit-twiddling. */ upb_decoderet upb_vdecode_max8_wright(upb_decoderet r) { uint64_t b; + uint64_t stop_bit; + upb_decoderet my_r; memcpy(&b, r.p, sizeof(b)); - uint64_t stop_bit = upb_get_vstopbit(b); + stop_bit = upb_get_vstopbit(b); b &= (stop_bit - 1); b = ((b & 0x7f007f007f007f00ULL) >> 1) | (b & 0x007f007f007f007fULL); b = ((b & 0xffff0000ffff0000ULL) >> 2) | (b & 0x0000ffff0000ffffULL); b = ((b & 0xffffffff00000000ULL) >> 4) | (b & 0x00000000ffffffffULL); if (stop_bit == 0) { - // Error: unterminated varint. + /* Error: unterminated varint. */ upb_decoderet err_r = {(void*)0, 0}; return err_r; } - upb_decoderet my_r = {r.p + ((__builtin_ctzll(stop_bit) + 1) / 8), - r.val | (b << 14)}; + my_r = upb_decoderet_make(r.p + ((__builtin_ctzll(stop_bit) + 1) / 8), + r.val | (b << 14)); return my_r; } @@ -9531,26 +9698,26 @@ upb_decoderet upb_vdecode_max8_wright(upb_decoderet r) { typedef struct { upb_sink sink; - // The current message in which we're parsing, and the field whose value we're - // expecting next. + /* The current message in which we're parsing, and the field whose value we're + * expecting next. */ const upb_msgdef *m; const upb_fielddef *f; - // We are in a repeated-field context, ready to emit mapentries as - // submessages. This flag alters the start-of-object (open-brace) behavior to - // begin a sequence of mapentry messages rather than a single submessage. + /* We are in a repeated-field context, ready to emit mapentries as + * submessages. This flag alters the start-of-object (open-brace) behavior to + * begin a sequence of mapentry messages rather than a single submessage. */ bool is_map; - // We are in a map-entry message context. This flag is set when parsing the - // value field of a single map entry and indicates to all value-field parsers - // (subobjects, strings, numbers, and bools) that the map-entry submessage - // should end as soon as the value is parsed. + /* We are in a map-entry message context. This flag is set when parsing the + * value field of a single map entry and indicates to all value-field parsers + * (subobjects, strings, numbers, and bools) that the map-entry submessage + * should end as soon as the value is parsed. */ bool is_mapentry; - // If |is_map| or |is_mapentry| is true, |mapfield| refers to the parent - // message's map field that we're currently parsing. This differs from |f| - // because |f| is the field in the *current* message (i.e., the map-entry - // message itself), not the parent's field that leads to this map. + /* If |is_map| or |is_mapentry| is true, |mapfield| refers to the parent + * message's map field that we're currently parsing. This differs from |f| + * because |f| is the field in the *current* message (i.e., the map-entry + * message itself), not the parent's field that leads to this map. */ const upb_fielddef *mapfield; } upb_jsonparser_frame; @@ -9559,41 +9726,41 @@ struct upb_json_parser { upb_byteshandler input_handler_; upb_bytessink input_; - // Stack to track the JSON scopes we are in. + /* Stack to track the JSON scopes we are in. */ upb_jsonparser_frame stack[UPB_JSON_MAX_DEPTH]; upb_jsonparser_frame *top; upb_jsonparser_frame *limit; upb_status *status; - // Ragel's internal parsing stack for the parsing state machine. + /* Ragel's internal parsing stack for the parsing state machine. */ int current_state; int parser_stack[UPB_JSON_MAX_DEPTH]; int parser_top; - // The handle for the current buffer. + /* The handle for the current buffer. */ const upb_bufhandle *handle; - // Accumulate buffer. See details in parser.rl. + /* Accumulate buffer. See details in parser.rl. */ const char *accumulated; size_t accumulated_len; char *accumulate_buf; size_t accumulate_buf_size; - // Multi-part text data. See details in parser.rl. + /* Multi-part text data. See details in parser.rl. */ int multipart_state; upb_selector_t string_selector; - // Input capture. See details in parser.rl. + /* Input capture. See details in parser.rl. */ const char *capture; - // Intermediate result of parsing a unicode escape sequence. + /* Intermediate result of parsing a unicode escape sequence. */ uint32_t digit; }; #define PARSER_CHECK_RETURN(x) if (!(x)) return false -// Used to signal that a capture has been suspended. +/* Used to signal that a capture has been suspended. */ static char suspend_capture; static upb_selector_t getsel_for_handlertype(upb_json_parser *p, @@ -9618,8 +9785,8 @@ static bool check_stack(upb_json_parser *p) { return true; } -// There are GCC/Clang built-ins for overflow checking which we could start -// using if there was any performance benefit to it. +/* There are GCC/Clang built-ins for overflow checking which we could start + * using if there was any performance benefit to it. */ static bool checked_add(size_t a, size_t b, size_t *c) { if (SIZE_MAX - a < b) return false; @@ -9628,7 +9795,7 @@ static bool checked_add(size_t a, size_t b, size_t *c) { } static size_t saturating_multiply(size_t a, size_t b) { - // size_t is unsigned, so this is defined behavior even on overflow. + /* size_t is unsigned, so this is defined behavior even on overflow. */ size_t ret = a * b; if (b != 0 && ret / b != a) { ret = SIZE_MAX; @@ -9639,7 +9806,7 @@ static size_t saturating_multiply(size_t a, size_t b) { /* Base64 decoding ************************************************************/ -// TODO(haberman): make this streaming. +/* TODO(haberman): make this streaming. */ static const signed char b64table[] = { -1, -1, -1, -1, -1, -1, -1, -1, @@ -9676,19 +9843,22 @@ static const signed char b64table[] = { -1, -1, -1, -1, -1, -1, -1, -1 }; -// Returns the table value sign-extended to 32 bits. Knowing that the upper -// bits will be 1 for unrecognized characters makes it easier to check for -// this error condition later (see below). +/* Returns the table value sign-extended to 32 bits. Knowing that the upper + * bits will be 1 for unrecognized characters makes it easier to check for + * this error condition later (see below). */ int32_t b64lookup(unsigned char ch) { return b64table[ch]; } -// Returns true if the given character is not a valid base64 character or -// padding. +/* Returns true if the given character is not a valid base64 character or + * padding. */ bool nonbase64(unsigned char ch) { return b64lookup(ch) == -1 && ch != '='; } static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr, size_t len) { const char *limit = ptr + len; for (; ptr < limit; ptr += 4) { + uint32_t val; + char output[3]; + if (limit - ptr < 4) { upb_status_seterrf(p->status, "Base64 input for bytes field not a multiple of 4: %s", @@ -9696,17 +9866,16 @@ static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr, return false; } - uint32_t val = b64lookup(ptr[0]) << 18 | - b64lookup(ptr[1]) << 12 | - b64lookup(ptr[2]) << 6 | - b64lookup(ptr[3]); + val = b64lookup(ptr[0]) << 18 | + b64lookup(ptr[1]) << 12 | + b64lookup(ptr[2]) << 6 | + b64lookup(ptr[3]); - // Test the upper bit; returns true if any of the characters returned -1. + /* Test the upper bit; returns true if any of the characters returned -1. */ if (val & 0x80000000) { goto otherchar; } - char output[3]; output[0] = val >> 16; output[1] = (val >> 8) & 0xff; output[2] = val & 0xff; @@ -9722,29 +9891,34 @@ otherchar: upb_fielddef_name(p->top->f)); return false; } if (ptr[2] == '=') { - // Last group contains only two input bytes, one output byte. + uint32_t val; + char output; + + /* Last group contains only two input bytes, one output byte. */ if (ptr[0] == '=' || ptr[1] == '=' || ptr[3] != '=') { goto badpadding; } - uint32_t val = b64lookup(ptr[0]) << 18 | - b64lookup(ptr[1]) << 12; + val = b64lookup(ptr[0]) << 18 | + b64lookup(ptr[1]) << 12; assert(!(val & 0x80000000)); - char output = val >> 16; + output = val >> 16; upb_sink_putstring(&p->top->sink, sel, &output, 1, NULL); return true; } else { - // Last group contains only three input bytes, two output bytes. + uint32_t val; + char output[2]; + + /* Last group contains only three input bytes, two output bytes. */ if (ptr[0] == '=' || ptr[1] == '=' || ptr[2] == '=') { goto badpadding; } - uint32_t val = b64lookup(ptr[0]) << 18 | - b64lookup(ptr[1]) << 12 | - b64lookup(ptr[2]) << 6; + val = b64lookup(ptr[0]) << 18 | + b64lookup(ptr[1]) << 12 | + b64lookup(ptr[2]) << 6; - char output[2]; output[0] = val >> 16; output[1] = (val >> 8) & 0xff; upb_sink_putstring(&p->top->sink, sel, output, 2, NULL); @@ -9762,23 +9936,23 @@ badpadding: /* Accumulate buffer **********************************************************/ -// Functionality for accumulating a buffer. -// -// Some parts of the parser need an entire value as a contiguous string. For -// example, to look up a member name in a hash table, or to turn a string into -// a number, the relevant library routines need the input string to be in -// contiguous memory, even if the value spanned two or more buffers in the -// input. These routines handle that. -// -// In the common case we can just point to the input buffer to get this -// contiguous string and avoid any actual copy. So we optimistically begin -// this way. But there are a few cases where we must instead copy into a -// separate buffer: -// -// 1. The string was not contiguous in the input (it spanned buffers). -// -// 2. The string included escape sequences that need to be interpreted to get -// the true value in a contiguous buffer. +/* Functionality for accumulating a buffer. + * + * Some parts of the parser need an entire value as a contiguous string. For + * example, to look up a member name in a hash table, or to turn a string into + * a number, the relevant library routines need the input string to be in + * contiguous memory, even if the value spanned two or more buffers in the + * input. These routines handle that. + * + * In the common case we can just point to the input buffer to get this + * contiguous string and avoid any actual copy. So we optimistically begin + * this way. But there are a few cases where we must instead copy into a + * separate buffer: + * + * 1. The string was not contiguous in the input (it spanned buffers). + * + * 2. The string included escape sequences that need to be interpreted to get + * the true value in a contiguous buffer. */ static void assert_accumulate_empty(upb_json_parser *p) { UPB_UNUSED(p); @@ -9791,15 +9965,16 @@ static void accumulate_clear(upb_json_parser *p) { p->accumulated_len = 0; } -// Used internally by accumulate_append(). +/* Used internally by accumulate_append(). */ static bool accumulate_realloc(upb_json_parser *p, size_t need) { + void *mem; size_t old_size = p->accumulate_buf_size; size_t new_size = UPB_MAX(old_size, 128); while (new_size < need) { new_size = saturating_multiply(new_size, 2); } - void *mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size); + mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size); if (!mem) { upb_status_seterrmsg(p->status, "Out of memory allocating buffer."); return false; @@ -9810,18 +9985,19 @@ static bool accumulate_realloc(upb_json_parser *p, size_t need) { return true; } -// Logically appends the given data to the append buffer. -// If "can_alias" is true, we will try to avoid actually copying, but the buffer -// must be valid until the next accumulate_append() call (if any). +/* Logically appends the given data to the append buffer. + * If "can_alias" is true, we will try to avoid actually copying, but the buffer + * must be valid until the next accumulate_append() call (if any). */ static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len, bool can_alias) { + size_t need; + if (!p->accumulated && can_alias) { p->accumulated = buf; p->accumulated_len = len; return true; } - size_t need; if (!checked_add(p->accumulated_len, len, &need)) { upb_status_seterrmsg(p->status, "Integer overflow."); return false; @@ -9841,9 +10017,9 @@ static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len, return true; } -// Returns a pointer to the data accumulated since the last accumulate_clear() -// call, and writes the length to *len. This with point either to the input -// buffer or a temporary accumulate buffer. +/* Returns a pointer to the data accumulated since the last accumulate_clear() + * call, and writes the length to *len. This with point either to the input + * buffer or a temporary accumulate buffer. */ static const char *accumulate_getptr(upb_json_parser *p, size_t *len) { assert(p->accumulated); *len = p->accumulated_len; @@ -9853,42 +10029,42 @@ static const char *accumulate_getptr(upb_json_parser *p, size_t *len) { /* Mult-part text data ********************************************************/ -// When we have text data in the input, it can often come in multiple segments. -// For example, there may be some raw string data followed by an escape -// sequence. The two segments are processed with different logic. Also buffer -// seams in the input can cause multiple segments. -// -// As we see segments, there are two main cases for how we want to process them: -// -// 1. we want to push the captured input directly to string handlers. -// -// 2. we need to accumulate all the parts into a contiguous buffer for further -// processing (field name lookup, string->number conversion, etc). - -// This is the set of states for p->multipart_state. +/* When we have text data in the input, it can often come in multiple segments. + * For example, there may be some raw string data followed by an escape + * sequence. The two segments are processed with different logic. Also buffer + * seams in the input can cause multiple segments. + * + * As we see segments, there are two main cases for how we want to process them: + * + * 1. we want to push the captured input directly to string handlers. + * + * 2. we need to accumulate all the parts into a contiguous buffer for further + * processing (field name lookup, string->number conversion, etc). */ + +/* This is the set of states for p->multipart_state. */ enum { - // We are not currently processing multipart data. + /* We are not currently processing multipart data. */ MULTIPART_INACTIVE = 0, - // We are processing multipart data by accumulating it into a contiguous - // buffer. + /* We are processing multipart data by accumulating it into a contiguous + * buffer. */ MULTIPART_ACCUMULATE = 1, - // We are processing multipart data by pushing each part directly to the - // current string handlers. + /* We are processing multipart data by pushing each part directly to the + * current string handlers. */ MULTIPART_PUSHEAGERLY = 2 }; -// Start a multi-part text value where we accumulate the data for processing at -// the end. +/* Start a multi-part text value where we accumulate the data for processing at + * the end. */ static void multipart_startaccum(upb_json_parser *p) { assert_accumulate_empty(p); assert(p->multipart_state == MULTIPART_INACTIVE); p->multipart_state = MULTIPART_ACCUMULATE; } -// Start a multi-part text value where we immediately push text data to a string -// value with the given selector. +/* Start a multi-part text value where we immediately push text data to a string + * value with the given selector. */ static void multipart_start(upb_json_parser *p, upb_selector_t sel) { assert_accumulate_empty(p); assert(p->multipart_state == MULTIPART_INACTIVE); @@ -9920,8 +10096,8 @@ static bool multipart_text(upb_json_parser *p, const char *buf, size_t len, return true; } -// Note: this invalidates the accumulate buffer! Call only after reading its -// contents. +/* Note: this invalidates the accumulate buffer! Call only after reading its + * contents. */ static void multipart_end(upb_json_parser *p) { assert(p->multipart_state != MULTIPART_INACTIVE); p->multipart_state = MULTIPART_INACTIVE; @@ -9931,9 +10107,9 @@ static void multipart_end(upb_json_parser *p) { /* Input capture **************************************************************/ -// Functionality for capturing a region of the input as text. Gracefully -// handles the case where a buffer seam occurs in the middle of the captured -// region. +/* Functionality for capturing a region of the input as text. Gracefully + * handles the case where a buffer seam occurs in the middle of the captured + * region. */ static void capture_begin(upb_json_parser *p, const char *ptr) { assert(p->multipart_state != MULTIPART_INACTIVE); @@ -9951,24 +10127,24 @@ static bool capture_end(upb_json_parser *p, const char *ptr) { } } -// This is called at the end of each input buffer (ie. when we have hit a -// buffer seam). If we are in the middle of capturing the input, this -// processes the unprocessed capture region. +/* This is called at the end of each input buffer (ie. when we have hit a + * buffer seam). If we are in the middle of capturing the input, this + * processes the unprocessed capture region. */ static void capture_suspend(upb_json_parser *p, const char **ptr) { if (!p->capture) return; if (multipart_text(p, p->capture, *ptr - p->capture, false)) { - // We use this as a signal that we were in the middle of capturing, and - // that capturing should resume at the beginning of the next buffer. - // - // We can't use *ptr here, because we have no guarantee that this pointer - // will be valid when we resume (if the underlying memory is freed, then - // using the pointer at all, even to compare to NULL, is likely undefined - // behavior). + /* We use this as a signal that we were in the middle of capturing, and + * that capturing should resume at the beginning of the next buffer. + * + * We can't use *ptr here, because we have no guarantee that this pointer + * will be valid when we resume (if the underlying memory is freed, then + * using the pointer at all, even to compare to NULL, is likely undefined + * behavior). */ p->capture = &suspend_capture; } else { - // Need to back up the pointer to the beginning of the capture, since - // we were not able to actually preserve it. + /* Need to back up the pointer to the beginning of the capture, since + * we were not able to actually preserve it. */ *ptr = p->capture; } } @@ -9983,8 +10159,8 @@ static void capture_resume(upb_json_parser *p, const char *ptr) { /* Callbacks from the parser **************************************************/ -// These are the functions called directly from the parser itself. -// We define these in the same order as their declarations in the parser. +/* These are the functions called directly from the parser itself. + * We define these in the same order as their declarations in the parser. */ static char escape_char(char in) { switch (in) { @@ -10029,8 +10205,8 @@ static void hexdigit(upb_json_parser *p, const char *ptr) { static bool end_hex(upb_json_parser *p) { uint32_t codepoint = p->digit; - // emit the codepoint as UTF-8. - char utf8[3]; // support \u0000 -- \uFFFF -- need only three bytes. + /* emit the codepoint as UTF-8. */ + char utf8[3]; /* support \u0000 -- \uFFFF -- need only three bytes. */ int length = 0; if (codepoint <= 0x7F) { utf8[0] = codepoint; @@ -10048,8 +10224,8 @@ static bool end_hex(upb_json_parser *p) { utf8[0] = (codepoint & 0x0F) | 0xE0; length = 3; } - // TODO(haberman): Handle high surrogates: if codepoint is a high surrogate - // we have to wait for the next escape to get the full code point). + /* TODO(haberman): Handle high surrogates: if codepoint is a high surrogate + * we have to wait for the next escape to get the full code point). */ return multipart_text(p, utf8, length, false); } @@ -10078,17 +10254,29 @@ static bool end_number(upb_json_parser *p, const char *ptr) { } static bool parse_number(upb_json_parser *p) { - // strtol() and friends unfortunately do not support specifying the length of - // the input string, so we need to force a copy into a NULL-terminated buffer. + size_t len; + const char *buf; + const char *myend; + char *end; + + /* strtol() and friends unfortunately do not support specifying the length of + * the input string, so we need to force a copy into a NULL-terminated buffer. */ if (!multipart_text(p, "\0", 1, false)) { return false; } - size_t len; - const char *buf = accumulate_getptr(p, &len); - const char *myend = buf + len - 1; // One for NULL. + buf = accumulate_getptr(p, &len); + myend = buf + len - 1; /* One for NULL. */ - char *end; + /* XXX: We are using strtol to parse integers, but this is wrong as even + * integers can be represented as 1e6 (for example), which strtol can't + * handle correctly. + * + * XXX: Also, we can't handle large integers properly because strto[u]ll + * isn't in C89. + * + * XXX: Also, we don't properly check floats for overflow, since strtof + * isn't in C89. */ switch (upb_fielddef_type(p->top->f)) { case UPB_TYPE_ENUM: case UPB_TYPE_INT32: { @@ -10100,7 +10288,7 @@ static bool parse_number(upb_json_parser *p) { break; } case UPB_TYPE_INT64: { - long long val = strtoll(p->accumulated, &end, 0); + long long val = strtol(p->accumulated, &end, 0); if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || end != myend) goto err; else @@ -10116,7 +10304,7 @@ static bool parse_number(upb_json_parser *p) { break; } case UPB_TYPE_UINT64: { - unsigned long long val = strtoull(p->accumulated, &end, 0); + unsigned long long val = strtoul(p->accumulated, &end, 0); if (val > UINT64_MAX || errno == ERANGE || end != myend) goto err; else @@ -10132,7 +10320,7 @@ static bool parse_number(upb_json_parser *p) { break; } case UPB_TYPE_FLOAT: { - float val = strtof(p->accumulated, &end); + float val = strtod(p->accumulated, &end); if (errno == ERANGE || end != myend) goto err; else @@ -10154,6 +10342,8 @@ err: } static bool parser_putbool(upb_json_parser *p, bool val) { + bool ok; + if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) { upb_status_seterrf(p->status, "Boolean value specified for non-bool field: %s", @@ -10161,7 +10351,7 @@ static bool parser_putbool(upb_json_parser *p, bool val) { return false; } - bool ok = upb_sink_putbool(&p->top->sink, parser_getsel(p), val); + ok = upb_sink_putbool(&p->top->sink, parser_getsel(p), val); UPB_ASSERT_VAR(ok, ok); return true; @@ -10171,12 +10361,15 @@ static bool start_stringval(upb_json_parser *p) { assert(p->top->f); if (upb_fielddef_isstring(p->top->f)) { + upb_jsonparser_frame *inner; + upb_selector_t sel; + if (!check_stack(p)) return false; - // Start a new parser frame: parser frames correspond one-to-one with - // handler frames, and string events occur in a sub-frame. - upb_jsonparser_frame *inner = p->top + 1; - upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR); + /* Start a new parser frame: parser frames correspond one-to-one with + * handler frames, and string events occur in a sub-frame. */ + inner = p->top + 1; + sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR); upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink); inner->m = p->top->m; inner->f = p->top->f; @@ -10185,11 +10378,11 @@ static bool start_stringval(upb_json_parser *p) { p->top = inner; if (upb_fielddef_type(p->top->f) == UPB_TYPE_STRING) { - // For STRING fields we push data directly to the handlers as it is - // parsed. We don't do this yet for BYTES fields, because our base64 - // decoder is not streaming. - // - // TODO(haberman): make base64 decoding streaming also. + /* For STRING fields we push data directly to the handlers as it is + * parsed. We don't do this yet for BYTES fields, because our base64 + * decoder is not streaming. + * + * TODO(haberman): make base64 decoding streaming also. */ multipart_start(p, getsel_for_handlertype(p, UPB_HANDLER_STRING)); return true; } else { @@ -10197,11 +10390,11 @@ static bool start_stringval(upb_json_parser *p) { return true; } } else if (upb_fielddef_type(p->top->f) == UPB_TYPE_ENUM) { - // No need to push a frame -- symbolic enum names in quotes remain in the - // current parser frame. - // - // Enum string values must accumulate so we can look up the value in a table - // once it is complete. + /* No need to push a frame -- symbolic enum names in quotes remain in the + * current parser frame. + * + * Enum string values must accumulate so we can look up the value in a table + * once it is complete. */ multipart_startaccum(p); return true; } else { @@ -10221,7 +10414,7 @@ static bool end_stringval(upb_json_parser *p) { p->accumulated, p->accumulated_len)) { return false; } - // Fall through. + /* Fall through. */ case UPB_TYPE_STRING: { upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR); @@ -10231,7 +10424,7 @@ static bool end_stringval(upb_json_parser *p) { } case UPB_TYPE_ENUM: { - // Resolve enum symbolic name to integer value. + /* Resolve enum symbolic name to integer value. */ const upb_enumdef *enumdef = (const upb_enumdef*)upb_fielddef_subdef(p->top->f); @@ -10268,18 +10461,18 @@ static void start_member(upb_json_parser *p) { multipart_startaccum(p); } -// Helper: invoked during parse_mapentry() to emit the mapentry message's key -// field based on the current contents of the accumulate buffer. +/* Helper: invoked during parse_mapentry() to emit the mapentry message's key + * field based on the current contents of the accumulate buffer. */ static bool parse_mapentry_key(upb_json_parser *p) { size_t len; const char *buf = accumulate_getptr(p, &len); - // Emit the key field. We do a bit of ad-hoc parsing here because the - // parser state machine has already decided that this is a string field - // name, and we are reinterpreting it as some arbitrary key type. In - // particular, integer and bool keys are quoted, so we need to parse the - // quoted string contents here. + /* Emit the key field. We do a bit of ad-hoc parsing here because the + * parser state machine has already decided that this is a string field + * name, and we are reinterpreting it as some arbitrary key type. In + * particular, integer and bool keys are quoted, so we need to parse the + * quoted string contents here. */ p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY); if (p->top->f == NULL) { @@ -10291,7 +10484,7 @@ static bool parse_mapentry_key(upb_json_parser *p) { case UPB_TYPE_INT64: case UPB_TYPE_UINT32: case UPB_TYPE_UINT64: - // Invoke end_number. The accum buffer has the number's text already. + /* Invoke end_number. The accum buffer has the number's text already. */ if (!parse_number(p)) { return false; } @@ -10332,47 +10525,52 @@ static bool parse_mapentry_key(upb_json_parser *p) { return true; } -// Helper: emit one map entry (as a submessage in the map field sequence). This -// is invoked from end_membername(), at the end of the map entry's key string, -// with the map key in the accumulate buffer. It parses the key from that -// buffer, emits the handler calls to start the mapentry submessage (setting up -// its subframe in the process), and sets up state in the subframe so that the -// value parser (invoked next) will emit the mapentry's value field and then -// end the mapentry message. +/* Helper: emit one map entry (as a submessage in the map field sequence). This + * is invoked from end_membername(), at the end of the map entry's key string, + * with the map key in the accumulate buffer. It parses the key from that + * buffer, emits the handler calls to start the mapentry submessage (setting up + * its subframe in the process), and sets up state in the subframe so that the + * value parser (invoked next) will emit the mapentry's value field and then + * end the mapentry message. */ static bool handle_mapentry(upb_json_parser *p) { - // Map entry: p->top->sink is the seq frame, so we need to start a frame - // for the mapentry itself, and then set |f| in that frame so that the map - // value field is parsed, and also set a flag to end the frame after the - // map-entry value is parsed. + const upb_fielddef *mapfield; + const upb_msgdef *mapentrymsg; + upb_jsonparser_frame *inner; + upb_selector_t sel; + + /* Map entry: p->top->sink is the seq frame, so we need to start a frame + * for the mapentry itself, and then set |f| in that frame so that the map + * value field is parsed, and also set a flag to end the frame after the + * map-entry value is parsed. */ if (!check_stack(p)) return false; - const upb_fielddef *mapfield = p->top->mapfield; - const upb_msgdef *mapentrymsg = upb_fielddef_msgsubdef(mapfield); + mapfield = p->top->mapfield; + mapentrymsg = upb_fielddef_msgsubdef(mapfield); - upb_jsonparser_frame *inner = p->top + 1; + inner = p->top + 1; p->top->f = mapfield; - upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG); + sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG); upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink); inner->m = mapentrymsg; inner->mapfield = mapfield; inner->is_map = false; - // Don't set this to true *yet* -- we reuse parsing handlers below to push - // the key field value to the sink, and these handlers will pop the frame - // if they see is_mapentry (when invoked by the parser state machine, they - // would have just seen the map-entry value, not key). + /* Don't set this to true *yet* -- we reuse parsing handlers below to push + * the key field value to the sink, and these handlers will pop the frame + * if they see is_mapentry (when invoked by the parser state machine, they + * would have just seen the map-entry value, not key). */ inner->is_mapentry = false; p->top = inner; - // send STARTMSG in submsg frame. + /* send STARTMSG in submsg frame. */ upb_sink_startmsg(&p->top->sink); parse_mapentry_key(p); - // Set up the value field to receive the map-entry value. + /* Set up the value field to receive the map-entry value. */ p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_VALUE); - p->top->is_mapentry = true; // set up to pop frame after value is parsed. + p->top->is_mapentry = true; /* set up to pop frame after value is parsed. */ p->top->mapfield = mapfield; if (p->top->f == NULL) { upb_status_seterrmsg(p->status, "mapentry message has no value"); @@ -10393,7 +10591,8 @@ static bool end_membername(upb_json_parser *p) { const upb_fielddef *f = upb_msgdef_ntof(p->top->m, buf, len); if (!f) { - // TODO(haberman): Ignore unknown fields if requested/configured to do so. + /* TODO(haberman): Ignore unknown fields if requested/configured to do + * so. */ upb_status_seterrf(p->status, "No such field: %.*s\n", (int)len, buf); return false; } @@ -10406,19 +10605,21 @@ static bool end_membername(upb_json_parser *p) { } static void end_member(upb_json_parser *p) { - // If we just parsed a map-entry value, end that frame too. + /* If we just parsed a map-entry value, end that frame too. */ if (p->top->is_mapentry) { - assert(p->top > p->stack); - // send ENDMSG on submsg. upb_status s = UPB_STATUS_INIT; + upb_selector_t sel; + bool ok; + const upb_fielddef *mapfield; + + assert(p->top > p->stack); + /* send ENDMSG on submsg. */ upb_sink_endmsg(&p->top->sink, &s); - const upb_fielddef* mapfield = p->top->mapfield; + mapfield = p->top->mapfield; - // send ENDSUBMSG in repeated-field-of-mapentries frame. + /* send ENDSUBMSG in repeated-field-of-mapentries frame. */ p->top--; - upb_selector_t sel; - bool ok = upb_handlers_getselector(mapfield, - UPB_HANDLER_ENDSUBMSG, &sel); + ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel); UPB_ASSERT_VAR(ok, ok); upb_sink_endsubmsg(&p->top->sink, sel); } @@ -10430,12 +10631,15 @@ static bool start_subobject(upb_json_parser *p) { assert(p->top->f); if (upb_fielddef_ismap(p->top->f)) { - // Beginning of a map. Start a new parser frame in a repeated-field - // context. + upb_jsonparser_frame *inner; + upb_selector_t sel; + + /* Beginning of a map. Start a new parser frame in a repeated-field + * context. */ if (!check_stack(p)) return false; - upb_jsonparser_frame *inner = p->top + 1; - upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ); + inner = p->top + 1; + sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ); upb_sink_startseq(&p->top->sink, sel, &inner->sink); inner->m = upb_fielddef_msgsubdef(p->top->f); inner->mapfield = p->top->f; @@ -10446,13 +10650,16 @@ static bool start_subobject(upb_json_parser *p) { return true; } else if (upb_fielddef_issubmsg(p->top->f)) { - // Beginning of a subobject. Start a new parser frame in the submsg - // context. + upb_jsonparser_frame *inner; + upb_selector_t sel; + + /* Beginning of a subobject. Start a new parser frame in the submsg + * context. */ if (!check_stack(p)) return false; - upb_jsonparser_frame *inner = p->top + 1; + inner = p->top + 1; - upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG); + sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG); upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink); inner->m = upb_fielddef_msgsubdef(p->top->f); inner->f = NULL; @@ -10471,17 +10678,22 @@ static bool start_subobject(upb_json_parser *p) { static void end_subobject(upb_json_parser *p) { if (p->top->is_map) { + upb_selector_t sel; p->top--; - upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ); + sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ); upb_sink_endseq(&p->top->sink, sel); } else { + upb_selector_t sel; p->top--; - upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG); + sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG); upb_sink_endsubmsg(&p->top->sink, sel); } } static bool start_array(upb_json_parser *p) { + upb_jsonparser_frame *inner; + upb_selector_t sel; + assert(p->top->f); if (!upb_fielddef_isseq(p->top->f)) { @@ -10493,8 +10705,8 @@ static bool start_array(upb_json_parser *p) { if (!check_stack(p)) return false; - upb_jsonparser_frame *inner = p->top + 1; - upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ); + inner = p->top + 1; + sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ); upb_sink_startseq(&p->top->sink, sel, &inner->sink); inner->m = p->top->m; inner->f = p->top->f; @@ -10506,10 +10718,12 @@ static bool start_array(upb_json_parser *p) { } static void end_array(upb_json_parser *p) { + upb_selector_t sel; + assert(p->top > p->stack); p->top--; - upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ); + sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ); upb_sink_endseq(&p->top->sink, sel); } @@ -10532,27 +10746,27 @@ static void end_object(upb_json_parser *p) { /* The actual parser **********************************************************/ -// What follows is the Ragel parser itself. The language is specified in Ragel -// and the actions call our C functions above. -// -// Ragel has an extensive set of functionality, and we use only a small part of -// it. There are many action types but we only use a few: -// -// ">" -- transition into a machine -// "%" -- transition out of a machine -// "@" -- transition into a final state of a machine. -// -// "@" transitions are tricky because a machine can transition into a final -// state repeatedly. But in some cases we know this can't happen, for example -// a string which is delimited by a final '"' can only transition into its -// final state once, when the closing '"' is seen. +/* What follows is the Ragel parser itself. The language is specified in Ragel + * and the actions call our C functions above. + * + * Ragel has an extensive set of functionality, and we use only a small part of + * it. There are many action types but we only use a few: + * + * ">" -- transition into a machine + * "%" -- transition out of a machine + * "@" -- transition into a final state of a machine. + * + * "@" transitions are tricky because a machine can transition into a final + * state repeatedly. But in some cases we know this can't happen, for example + * a string which is delimited by a final '"' can only transition into its + * final state once, when the closing '"' is seen. */ -#line 1151 "upb/json/parser.rl" +#line 1198 "upb/json/parser.rl" -#line 1063 "upb/json/parser.c" +#line 1110 "upb/json/parser.c" static const char _json_actions[] = { 0, 1, 0, 1, 2, 1, 3, 1, 5, 1, 6, 1, 7, 1, 8, 1, @@ -10701,16 +10915,13 @@ static const int json_en_value_machine = 27; static const int json_en_main = 1; -#line 1154 "upb/json/parser.rl" +#line 1201 "upb/json/parser.rl" size_t parse(void *closure, const void *hd, const char *buf, size_t size, const upb_bufhandle *handle) { - UPB_UNUSED(hd); - UPB_UNUSED(handle); upb_json_parser *parser = closure; - parser->handle = handle; - // Variables used by Ragel's generated code. + /* Variables used by Ragel's generated code. */ int cs = parser->current_state; int *stack = parser->parser_stack; int top = parser->parser_top; @@ -10718,10 +10929,15 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size, const char *p = buf; const char *pe = buf + size; + parser->handle = handle; + + UPB_UNUSED(hd); + UPB_UNUSED(handle); + capture_resume(parser, buf); -#line 1232 "upb/json/parser.c" +#line 1281 "upb/json/parser.c" { int _klen; unsigned int _trans; @@ -10796,118 +11012,118 @@ _match: switch ( *_acts++ ) { case 0: -#line 1066 "upb/json/parser.rl" +#line 1113 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 1: -#line 1067 "upb/json/parser.rl" +#line 1114 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 10; goto _again;} } break; case 2: -#line 1071 "upb/json/parser.rl" +#line 1118 "upb/json/parser.rl" { start_text(parser, p); } break; case 3: -#line 1072 "upb/json/parser.rl" +#line 1119 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_text(parser, p)); } break; case 4: -#line 1078 "upb/json/parser.rl" +#line 1125 "upb/json/parser.rl" { start_hex(parser); } break; case 5: -#line 1079 "upb/json/parser.rl" +#line 1126 "upb/json/parser.rl" { hexdigit(parser, p); } break; case 6: -#line 1080 "upb/json/parser.rl" +#line 1127 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_hex(parser)); } break; case 7: -#line 1086 "upb/json/parser.rl" +#line 1133 "upb/json/parser.rl" { CHECK_RETURN_TOP(escape(parser, p)); } break; case 8: -#line 1092 "upb/json/parser.rl" +#line 1139 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 9: -#line 1095 "upb/json/parser.rl" +#line 1142 "upb/json/parser.rl" { {stack[top++] = cs; cs = 19; goto _again;} } break; case 10: -#line 1097 "upb/json/parser.rl" +#line 1144 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 27; goto _again;} } break; case 11: -#line 1102 "upb/json/parser.rl" +#line 1149 "upb/json/parser.rl" { start_member(parser); } break; case 12: -#line 1103 "upb/json/parser.rl" +#line 1150 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_membername(parser)); } break; case 13: -#line 1106 "upb/json/parser.rl" +#line 1153 "upb/json/parser.rl" { end_member(parser); } break; case 14: -#line 1112 "upb/json/parser.rl" +#line 1159 "upb/json/parser.rl" { start_object(parser); } break; case 15: -#line 1115 "upb/json/parser.rl" +#line 1162 "upb/json/parser.rl" { end_object(parser); } break; case 16: -#line 1121 "upb/json/parser.rl" +#line 1168 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_array(parser)); } break; case 17: -#line 1125 "upb/json/parser.rl" +#line 1172 "upb/json/parser.rl" { end_array(parser); } break; case 18: -#line 1130 "upb/json/parser.rl" +#line 1177 "upb/json/parser.rl" { start_number(parser, p); } break; case 19: -#line 1131 "upb/json/parser.rl" +#line 1178 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 20: -#line 1133 "upb/json/parser.rl" +#line 1180 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_stringval(parser)); } break; case 21: -#line 1134 "upb/json/parser.rl" +#line 1181 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_stringval(parser)); } break; case 22: -#line 1136 "upb/json/parser.rl" +#line 1183 "upb/json/parser.rl" { CHECK_RETURN_TOP(parser_putbool(parser, true)); } break; case 23: -#line 1138 "upb/json/parser.rl" +#line 1185 "upb/json/parser.rl" { CHECK_RETURN_TOP(parser_putbool(parser, false)); } break; case 24: -#line 1140 "upb/json/parser.rl" +#line 1187 "upb/json/parser.rl" { /* null value */ } break; case 25: -#line 1142 "upb/json/parser.rl" +#line 1189 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_subobject(parser)); } break; case 26: -#line 1143 "upb/json/parser.rl" +#line 1190 "upb/json/parser.rl" { end_subobject(parser); } break; case 27: -#line 1148 "upb/json/parser.rl" +#line 1195 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; -#line 1418 "upb/json/parser.c" +#line 1467 "upb/json/parser.c" } } @@ -10920,7 +11136,7 @@ _again: _out: {} } -#line 1173 "upb/json/parser.rl" +#line 1222 "upb/json/parser.rl" if (p != pe) { upb_status_seterrf(parser->status, "Parse error at %s\n", p); @@ -10929,7 +11145,7 @@ _again: } error: - // Save parsing state back to parser. + /* Save parsing state back to parser. */ parser->current_state = cs; parser->parser_top = top; @@ -10940,7 +11156,7 @@ bool end(void *closure, const void *hd) { UPB_UNUSED(closure); UPB_UNUSED(hd); - // Prevent compile warning on unused static constants. + /* Prevent compile warning on unused static constants. */ UPB_UNUSED(json_start); UPB_UNUSED(json_en_number_machine); UPB_UNUSED(json_en_string_machine); @@ -10950,22 +11166,23 @@ bool end(void *closure, const void *hd) { } static void json_parser_reset(upb_json_parser *p) { + int cs; + int top; + p->top = p->stack; p->top->f = NULL; p->top->is_map = false; p->top->is_mapentry = false; - int cs; - int top; - // Emit Ragel initialization of the parser. + /* Emit Ragel initialization of the parser. */ -#line 1470 "upb/json/parser.c" +#line 1520 "upb/json/parser.c" { cs = json_start; top = 0; } -#line 1211 "upb/json/parser.rl" +#line 1261 "upb/json/parser.rl" p->current_state = cs; p->parser_top = top; accumulate_clear(p); @@ -10997,8 +11214,8 @@ upb_json_parser *upb_json_parser_create(upb_env *env, upb_sink *output) { upb_sink_reset(&p->top->sink, output->handlers, output->closure); p->top->m = upb_handlers_msgdef(output->handlers); - // If this fails, uncomment and increase the value in parser.h. - // fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); + /* If this fails, uncomment and increase the value in parser.h. + * fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */ assert(upb_env_bytesallocated(env) - size_before <= UPB_JSON_PARSER_SIZE); return p; } @@ -11024,26 +11241,26 @@ upb_bytessink *upb_json_parser_input(upb_json_parser *p) { struct upb_json_printer { upb_sink input_; - // BytesSink closure. + /* BytesSink closure. */ void *subc_; upb_bytessink *output_; - // We track the depth so that we know when to emit startstr/endstr on the - // output. + /* We track the depth so that we know when to emit startstr/endstr on the + * output. */ int depth_; - // Have we emitted the first element? This state is necessary to emit commas - // without leaving a trailing comma in arrays/maps. We keep this state per - // frame depth. - // - // Why max_depth * 2? UPB_MAX_HANDLER_DEPTH counts depth as nested messages. - // We count frames (contexts in which we separate elements by commas) as both - // repeated fields and messages (maps), and the worst case is a - // message->repeated field->submessage->repeated field->... nesting. + /* Have we emitted the first element? This state is necessary to emit commas + * without leaving a trailing comma in arrays/maps. We keep this state per + * frame depth. + * + * Why max_depth * 2? UPB_MAX_HANDLER_DEPTH counts depth as nested messages. + * We count frames (contexts in which we separate elements by commas) as both + * repeated fields and messages (maps), and the worst case is a + * message->repeated field->submessage->repeated field->... nesting. */ bool first_elem_[UPB_MAX_HANDLER_DEPTH * 2]; }; -// StringPiece; a pointer plus a length. +/* StringPiece; a pointer plus a length. */ typedef struct { const char *ptr; size_t len; @@ -11057,11 +11274,11 @@ strpc *newstrpc(upb_handlers *h, const upb_fielddef *f) { return ret; } -// ------------ JSON string printing: values, maps, arrays -------------------- +/* ------------ JSON string printing: values, maps, arrays ------------------ */ static void print_data( upb_json_printer *p, const char *buf, unsigned int len) { - // TODO: Will need to change if we support pushback from the sink. + /* TODO: Will need to change if we support pushback from the sink. */ size_t n = upb_bytessink_putbuf(p->output_, p->subc_, buf, len, NULL); UPB_ASSERT_VAR(n, n == len); } @@ -11073,18 +11290,18 @@ static void print_comma(upb_json_printer *p) { p->first_elem_[p->depth_] = false; } -// Helpers that print properly formatted elements to the JSON output stream. +/* Helpers that print properly formatted elements to the JSON output stream. */ -// Used for escaping control chars in strings. +/* Used for escaping control chars in strings. */ static const char kControlCharLimit = 0x20; -static inline bool is_json_escaped(char c) { - // See RFC 4627. +UPB_INLINE bool is_json_escaped(char c) { + /* See RFC 4627. */ unsigned char uc = (unsigned char)c; return uc < kControlCharLimit || uc == '"' || uc == '\\'; } -static inline char* json_nice_escape(char c) { +UPB_INLINE char* json_nice_escape(char c) { switch (c) { case '"': return "\\\""; case '\\': return "\\\\"; @@ -11097,46 +11314,47 @@ static inline char* json_nice_escape(char c) { } } -// Write a properly escaped string chunk. The surrounding quotes are *not* -// printed; this is so that the caller has the option of emitting the string -// content in chunks. +/* Write a properly escaped string chunk. The surrounding quotes are *not* + * printed; this is so that the caller has the option of emitting the string + * content in chunks. */ static void putstring(upb_json_printer *p, const char *buf, unsigned int len) { const char* unescaped_run = NULL; - for (unsigned int i = 0; i < len; i++) { + unsigned int i; + for (i = 0; i < len; i++) { char c = buf[i]; - // Handle escaping. + /* Handle escaping. */ if (is_json_escaped(c)) { - // Use a "nice" escape, like \n, if one exists for this character. + /* Use a "nice" escape, like \n, if one exists for this character. */ const char* escape = json_nice_escape(c); - // If we don't have a specific 'nice' escape code, use a \uXXXX-style - // escape. + /* If we don't have a specific 'nice' escape code, use a \uXXXX-style + * escape. */ char escape_buf[8]; if (!escape) { unsigned char byte = (unsigned char)c; - snprintf(escape_buf, sizeof(escape_buf), "\\u%04x", (int)byte); + _upb_snprintf(escape_buf, sizeof(escape_buf), "\\u%04x", (int)byte); escape = escape_buf; } - // N.B. that we assume that the input encoding is equal to the output - // encoding (both UTF-8 for now), so for chars >= 0x20 and != \, ", we - // can simply pass the bytes through. + /* N.B. that we assume that the input encoding is equal to the output + * encoding (both UTF-8 for now), so for chars >= 0x20 and != \, ", we + * can simply pass the bytes through. */ - // If there's a current run of unescaped chars, print that run first. + /* If there's a current run of unescaped chars, print that run first. */ if (unescaped_run) { print_data(p, unescaped_run, &buf[i] - unescaped_run); unescaped_run = NULL; } - // Then print the escape code. + /* Then print the escape code. */ print_data(p, escape, strlen(escape)); } else { - // Add to the current unescaped run of characters. + /* Add to the current unescaped run of characters. */ if (unescaped_run == NULL) { unescaped_run = &buf[i]; } } } - // If the string ended in a run of unescaped characters, print that last run. + /* If the string ended in a run of unescaped characters, print that last run. */ if (unescaped_run) { print_data(p, unescaped_run, &buf[len] - unescaped_run); } @@ -11144,42 +11362,42 @@ static void putstring(upb_json_printer *p, const char *buf, unsigned int len) { #define CHKLENGTH(x) if (!(x)) return -1; -// Helpers that format floating point values according to our custom formats. -// Right now we use %.8g and %.17g for float/double, respectively, to match -// proto2::util::JsonFormat's defaults. May want to change this later. +/* Helpers that format floating point values according to our custom formats. + * Right now we use %.8g and %.17g for float/double, respectively, to match + * proto2::util::JsonFormat's defaults. May want to change this later. */ static size_t fmt_double(double val, char* buf, size_t length) { - size_t n = snprintf(buf, length, "%.17g", val); + size_t n = _upb_snprintf(buf, length, "%.17g", val); CHKLENGTH(n > 0 && n < length); return n; } static size_t fmt_float(float val, char* buf, size_t length) { - size_t n = snprintf(buf, length, "%.8g", val); + size_t n = _upb_snprintf(buf, length, "%.8g", val); CHKLENGTH(n > 0 && n < length); return n; } static size_t fmt_bool(bool val, char* buf, size_t length) { - size_t n = snprintf(buf, length, "%s", (val ? "true" : "false")); + size_t n = _upb_snprintf(buf, length, "%s", (val ? "true" : "false")); CHKLENGTH(n > 0 && n < length); return n; } static size_t fmt_int64(long val, char* buf, size_t length) { - size_t n = snprintf(buf, length, "%ld", val); + size_t n = _upb_snprintf(buf, length, "%ld", val); CHKLENGTH(n > 0 && n < length); return n; } static size_t fmt_uint64(unsigned long long val, char* buf, size_t length) { - size_t n = snprintf(buf, length, "%llu", val); + size_t n = _upb_snprintf(buf, length, "%llu", val); CHKLENGTH(n > 0 && n < length); return n; } -// Print a map key given a field name. Called by scalar field handlers and by -// startseq for repeated fields. +/* Print a map key given a field name. Called by scalar field handlers and by + * startseq for repeated fields. */ static bool putkey(void *closure, const void *handler_data) { upb_json_printer *p = closure; const strpc *key = handler_data; @@ -11196,9 +11414,9 @@ static bool putkey(void *closure, const void *handler_data) { #define TYPE_HANDLERS(type, fmt_func) \ static bool put##type(void *closure, const void *handler_data, type val) { \ upb_json_printer *p = closure; \ - UPB_UNUSED(handler_data); \ char data[64]; \ size_t length = fmt_func(val, data, sizeof(data)); \ + UPB_UNUSED(handler_data); \ CHKFMT(length); \ print_data(p, data, length); \ return true; \ @@ -11227,20 +11445,20 @@ static bool putkey(void *closure, const void *handler_data) { return true; \ } -TYPE_HANDLERS(double, fmt_double); -TYPE_HANDLERS(float, fmt_float); -TYPE_HANDLERS(bool, fmt_bool); -TYPE_HANDLERS(int32_t, fmt_int64); -TYPE_HANDLERS(uint32_t, fmt_int64); -TYPE_HANDLERS(int64_t, fmt_int64); -TYPE_HANDLERS(uint64_t, fmt_uint64); +TYPE_HANDLERS(double, fmt_double) +TYPE_HANDLERS(float, fmt_float) +TYPE_HANDLERS(bool, fmt_bool) +TYPE_HANDLERS(int32_t, fmt_int64) +TYPE_HANDLERS(uint32_t, fmt_int64) +TYPE_HANDLERS(int64_t, fmt_int64) +TYPE_HANDLERS(uint64_t, fmt_uint64) -// double and float are not allowed to be map keys. -TYPE_HANDLERS_MAPKEY(bool, fmt_bool); -TYPE_HANDLERS_MAPKEY(int32_t, fmt_int64); -TYPE_HANDLERS_MAPKEY(uint32_t, fmt_int64); -TYPE_HANDLERS_MAPKEY(int64_t, fmt_int64); -TYPE_HANDLERS_MAPKEY(uint64_t, fmt_uint64); +/* double and float are not allowed to be map keys. */ +TYPE_HANDLERS_MAPKEY(bool, fmt_bool) +TYPE_HANDLERS_MAPKEY(int32_t, fmt_int64) +TYPE_HANDLERS_MAPKEY(uint32_t, fmt_int64) +TYPE_HANDLERS_MAPKEY(int64_t, fmt_int64) +TYPE_HANDLERS_MAPKEY(uint64_t, fmt_uint64) #undef TYPE_HANDLERS #undef TYPE_HANDLERS_MAPKEY @@ -11254,9 +11472,11 @@ static bool scalar_enum(void *closure, const void *handler_data, int32_t val) { const EnumHandlerData *hd = handler_data; upb_json_printer *p = closure; + const char *symbolic_name; + CHK(putkey(closure, hd->keyname)); - const char *symbolic_name = upb_enumdef_iton(hd->enumdef, val); + symbolic_name = upb_enumdef_iton(hd->enumdef, val); if (symbolic_name) { print_data(p, "\"", 1); putstring(p, symbolic_name, strlen(symbolic_name)); @@ -11307,8 +11527,8 @@ static void *scalar_startsubmsg(void *closure, const void *handler_data) { } static void *repeated_startsubmsg(void *closure, const void *handler_data) { - UPB_UNUSED(handler_data); upb_json_printer *p = closure; + UPB_UNUSED(handler_data); print_comma(p); return closure; } @@ -11325,8 +11545,8 @@ static void end_frame(upb_json_printer *p) { } static bool printer_startmsg(void *closure, const void *handler_data) { - UPB_UNUSED(handler_data); upb_json_printer *p = closure; + UPB_UNUSED(handler_data); if (p->depth_ == 0) { upb_bytessink_start(p->output_, 0, &p->subc_); } @@ -11335,9 +11555,9 @@ static bool printer_startmsg(void *closure, const void *handler_data) { } static bool printer_endmsg(void *closure, const void *handler_data, upb_status *s) { + upb_json_printer *p = closure; UPB_UNUSED(handler_data); UPB_UNUSED(s); - upb_json_printer *p = closure; end_frame(p); if (p->depth_ == 0) { upb_bytessink_end(p->output_); @@ -11355,8 +11575,8 @@ static void *startseq(void *closure, const void *handler_data) { } static bool endseq(void *closure, const void *handler_data) { - UPB_UNUSED(handler_data); upb_json_printer *p = closure; + UPB_UNUSED(handler_data); print_data(p, "]", 1); p->depth_--; return true; @@ -11372,8 +11592,8 @@ static void *startmap(void *closure, const void *handler_data) { } static bool endmap(void *closure, const void *handler_data) { - UPB_UNUSED(handler_data); upb_json_printer *p = closure; + UPB_UNUSED(handler_data); print_data(p, "}", 1); p->depth_--; return true; @@ -11381,32 +11601,35 @@ static bool endmap(void *closure, const void *handler_data) { static size_t putstr(void *closure, const void *handler_data, const char *str, size_t len, const upb_bufhandle *handle) { + upb_json_printer *p = closure; UPB_UNUSED(handler_data); UPB_UNUSED(handle); - upb_json_printer *p = closure; putstring(p, str, len); return len; } -// This has to Base64 encode the bytes, because JSON has no "bytes" type. +/* This has to Base64 encode the bytes, because JSON has no "bytes" type. */ static size_t putbytes(void *closure, const void *handler_data, const char *str, size_t len, const upb_bufhandle *handle) { - UPB_UNUSED(handler_data); - UPB_UNUSED(handle); upb_json_printer *p = closure; - // This is the regular base64, not the "web-safe" version. + /* This is the regular base64, not the "web-safe" version. */ static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - // Base64-encode. + /* Base64-encode. */ char data[16000]; const char *limit = data + sizeof(data); const unsigned char *from = (const unsigned char*)str; char *to = data; size_t remaining = len; + size_t bytes; + + UPB_UNUSED(handler_data); + UPB_UNUSED(handle); + while (remaining > 2) { - // TODO(haberman): handle encoded lengths > sizeof(data) + /* TODO(haberman): handle encoded lengths > sizeof(data) */ UPB_ASSERT_VAR(limit, (limit - to) >= 4); to[0] = base64[from[0] >> 2]; @@ -11438,7 +11661,7 @@ static size_t putbytes(void *closure, const void *handler_data, const char *str, break; } - size_t bytes = to - data; + bytes = to - data; print_data(p, "\"", 1); putstring(p, data, bytes); print_data(p, "\"", 1); @@ -11447,9 +11670,9 @@ static size_t putbytes(void *closure, const void *handler_data, const char *str, static void *scalar_startstr(void *closure, const void *handler_data, size_t size_hint) { + upb_json_printer *p = closure; UPB_UNUSED(handler_data); UPB_UNUSED(size_hint); - upb_json_printer *p = closure; CHK(putkey(closure, handler_data)); print_data(p, "\"", 1); return p; @@ -11463,17 +11686,17 @@ static size_t scalar_str(void *closure, const void *handler_data, } static bool scalar_endstr(void *closure, const void *handler_data) { - UPB_UNUSED(handler_data); upb_json_printer *p = closure; + UPB_UNUSED(handler_data); print_data(p, "\"", 1); return true; } static void *repeated_startstr(void *closure, const void *handler_data, size_t size_hint) { + upb_json_printer *p = closure; UPB_UNUSED(handler_data); UPB_UNUSED(size_hint); - upb_json_printer *p = closure; print_comma(p); print_data(p, "\"", 1); return p; @@ -11487,17 +11710,17 @@ static size_t repeated_str(void *closure, const void *handler_data, } static bool repeated_endstr(void *closure, const void *handler_data) { - UPB_UNUSED(handler_data); upb_json_printer *p = closure; + UPB_UNUSED(handler_data); print_data(p, "\"", 1); return true; } static void *mapkeyval_startstr(void *closure, const void *handler_data, size_t size_hint) { + upb_json_printer *p = closure; UPB_UNUSED(handler_data); UPB_UNUSED(size_hint); - upb_json_printer *p = closure; print_data(p, "\"", 1); return p; } @@ -11510,15 +11733,15 @@ static size_t mapkey_str(void *closure, const void *handler_data, } static bool mapkey_endstr(void *closure, const void *handler_data) { - UPB_UNUSED(handler_data); upb_json_printer *p = closure; + UPB_UNUSED(handler_data); print_data(p, "\":", 2); return true; } static bool mapvalue_endstr(void *closure, const void *handler_data) { - UPB_UNUSED(handler_data); upb_json_printer *p = closure; + UPB_UNUSED(handler_data); print_data(p, "\"", 1); return true; } @@ -11559,30 +11782,31 @@ static void set_enum_hd(upb_handlers *h, upb_handlerattr_sethandlerdata(attr, hd); } -// Set up handlers for a mapentry submessage (i.e., an individual key/value pair -// in a map). -// -// TODO: Handle missing key, missing value, out-of-order key/value, or repeated -// key or value cases properly. The right way to do this is to allocate a -// temporary structure at the start of a mapentry submessage, store key and -// value data in it as key and value handlers are called, and then print the -// key/value pair once at the end of the submessage. If we don't do this, we -// should at least detect the case and throw an error. However, so far all of -// our sources that emit mapentry messages do so canonically (with one key -// field, and then one value field), so this is not a pressing concern at the -// moment. +/* Set up handlers for a mapentry submessage (i.e., an individual key/value pair + * in a map). + * + * TODO: Handle missing key, missing value, out-of-order key/value, or repeated + * key or value cases properly. The right way to do this is to allocate a + * temporary structure at the start of a mapentry submessage, store key and + * value data in it as key and value handlers are called, and then print the + * key/value pair once at the end of the submessage. If we don't do this, we + * should at least detect the case and throw an error. However, so far all of + * our sources that emit mapentry messages do so canonically (with one key + * field, and then one value field), so this is not a pressing concern at the + * moment. */ void printer_sethandlers_mapentry(const void *closure, upb_handlers *h) { - UPB_UNUSED(closure); const upb_msgdef *md = upb_handlers_msgdef(h); - // A mapentry message is printed simply as '"key": value'. Rather than - // special-case key and value for every type below, we just handle both - // fields explicitly here. + /* A mapentry message is printed simply as '"key": value'. Rather than + * special-case key and value for every type below, we just handle both + * fields explicitly here. */ const upb_fielddef* key_field = upb_msgdef_itof(md, UPB_MAPENTRY_KEY); const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_MAPENTRY_VALUE); upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; + UPB_UNUSED(closure); + switch (upb_fielddef_type(key_field)) { case UPB_TYPE_INT32: upb_handlers_setint32(h, key_field, putmapkey_int32_t, &empty_attr); @@ -11650,8 +11874,8 @@ void printer_sethandlers_mapentry(const void *closure, upb_handlers *h) { break; } case UPB_TYPE_MESSAGE: - // No handler necessary -- the submsg handlers will print the message - // as appropriate. + /* No handler necessary -- the submsg handlers will print the message + * as appropriate. */ break; } @@ -11659,14 +11883,16 @@ void printer_sethandlers_mapentry(const void *closure, upb_handlers *h) { } void printer_sethandlers(const void *closure, upb_handlers *h) { - UPB_UNUSED(closure); const upb_msgdef *md = upb_handlers_msgdef(h); bool is_mapentry = upb_msgdef_mapentry(md); upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; + upb_msg_field_iter i; + + UPB_UNUSED(closure); if (is_mapentry) { - // mapentry messages are sufficiently different that we handle them - // separately. + /* mapentry messages are sufficiently different that we handle them + * separately. */ printer_sethandlers_mapentry(closure, h); return; } @@ -11683,7 +11909,6 @@ void printer_sethandlers(const void *closure, upb_handlers *h) { } \ break; - upb_msg_field_iter i; upb_msg_field_begin(&i, md); for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) { const upb_fielddef *f = upb_msg_iter_field(&i); @@ -11708,9 +11933,9 @@ void printer_sethandlers(const void *closure, upb_handlers *h) { TYPE(UPB_TYPE_INT64, int64, int64_t); TYPE(UPB_TYPE_UINT64, uint64, uint64_t); case UPB_TYPE_ENUM: { - // For now, we always emit symbolic names for enums. We may want an - // option later to control this behavior, but we will wait for a real - // need first. + /* For now, we always emit symbolic names for enums. We may want an + * option later to control this behavior, but we will wait for a real + * need first. */ upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER; set_enum_hd(h, f, &enum_attr); @@ -11735,8 +11960,8 @@ void printer_sethandlers(const void *closure, upb_handlers *h) { } break; case UPB_TYPE_BYTES: - // XXX: this doesn't support strings that span buffers yet. The base64 - // encoder will need to be made resumable for this to work properly. + /* XXX: this doesn't support strings that span buffers yet. The base64 + * encoder will need to be made resumable for this to work properly. */ if (upb_fielddef_isseq(f)) { upb_handlers_setstring(h, f, repeated_bytes, &empty_attr); } else { @@ -11779,7 +12004,7 @@ upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h, json_printer_reset(p); upb_sink_reset(&p->input_, h, p); - // If this fails, increase the value in printer.h. + /* If this fails, increase the value in printer.h. */ assert(upb_env_bytesallocated(e) - size_before <= UPB_JSON_PRINTER_SIZE); return p; } diff --git a/ruby/ext/google/protobuf_c/upb.h b/ruby/ext/google/protobuf_c/upb.h index 97df943a..b4dcd558 100644 --- a/ruby/ext/google/protobuf_c/upb.h +++ b/ruby/ext/google/protobuf_c/upb.h @@ -92,31 +92,61 @@ #include <stdbool.h> #include <stddef.h> -// inline if possible, emit standalone code if required. +/* UPB_INLINE: inline if possible, emit standalone code if required. */ #ifdef __cplusplus #define UPB_INLINE inline +#elif defined (__GNUC__) +#define UPB_INLINE static __inline__ #else -#define UPB_INLINE static inline +#define UPB_INLINE static #endif -// For use in C/C++ source files (not headers), forces inlining within the file. +/* Define UPB_BIG_ENDIAN manually if you're on big endian and your compiler + * doesn't provide these preprocessor symbols. */ +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +#define UPB_BIG_ENDIAN +#endif + +/* Macros for function attributes on compilers that support them. */ #ifdef __GNUC__ -#define UPB_FORCEINLINE inline __attribute__((always_inline)) +#define UPB_FORCEINLINE __inline__ __attribute__((always_inline)) #define UPB_NOINLINE __attribute__((noinline)) -#else +#define UPB_NORETURN __attribute__((__noreturn__)) +#else /* !defined(__GNUC__) */ #define UPB_FORCEINLINE #define UPB_NOINLINE +#define UPB_NORETURN #endif -#if __STDC_VERSION__ >= 199901L -#define UPB_C99 +/* A few hacky workarounds for functions not in C89. + * For internal use only! + * TODO(haberman): fix these by including our own implementations, or finding + * another workaround. + */ +#ifdef __GNUC__ +#define _upb_snprintf __builtin_snprintf +#define _upb_vsnprintf __builtin_vsnprintf +#define _upb_va_copy(a, b) __va_copy(a, b) +#elif __STDC_VERSION__ >= 199901L +/* C99 versions. */ +#define _upb_snprintf snprintf +#define _upb_vsnprintf vsnprintf +#define _upb_va_copy(a, b) va_copy(a, b) +#else +#error Need implementations of [v]snprintf and va_copy #endif + #if ((defined(__cplusplus) && __cplusplus >= 201103L) || \ defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(UPB_NO_CXX11) #define UPB_CXX11 #endif +/* UPB_DISALLOW_COPY_AND_ASSIGN() + * UPB_DISALLOW_POD_OPS() + * + * Declare these in the "private" section of a C++ class to forbid copy/assign + * or all POD ops (construct, destruct, copy, assign) on that class. */ #ifdef UPB_CXX11 #include <type_traits> #define UPB_DISALLOW_COPY_AND_ASSIGN(class_name) \ @@ -125,51 +155,53 @@ #define UPB_DISALLOW_POD_OPS(class_name, full_class_name) \ class_name() = delete; \ ~class_name() = delete; \ - /* Friend Pointer<T> so it can access base class. */ \ - friend class Pointer<full_class_name>; \ - friend class Pointer<const full_class_name>; \ UPB_DISALLOW_COPY_AND_ASSIGN(class_name) #define UPB_ASSERT_STDLAYOUT(type) \ static_assert(std::is_standard_layout<type>::value, \ #type " must be standard layout"); -#else // !defined(UPB_CXX11) +#else /* !defined(UPB_CXX11) */ #define UPB_DISALLOW_COPY_AND_ASSIGN(class_name) \ class_name(const class_name&); \ void operator=(const class_name&); #define UPB_DISALLOW_POD_OPS(class_name, full_class_name) \ class_name(); \ ~class_name(); \ - /* Friend Pointer<T> so it can access base class. */ \ - friend class Pointer<full_class_name>; \ - friend class Pointer<const full_class_name>; \ UPB_DISALLOW_COPY_AND_ASSIGN(class_name) #define UPB_ASSERT_STDLAYOUT(type) #endif +/* UPB_DECLARE_TYPE() + * UPB_DECLARE_DERIVED_TYPE() + * UPB_DECLARE_DERIVED_TYPE2() + * + * Macros for declaring C and C++ types both, including inheritance. + * The inheritance doesn't use real C++ inheritance, to stay compatible with C. + * + * These macros also provide upcasts: + * - in C: types-specific functions (ie. upb_foo_upcast(foo)) + * - in C++: upb::upcast(foo) along with implicit conversions + * + * Downcasts are not provided, but upb/def.h defines downcasts for upb::Def. */ + +#define UPB_C_UPCASTS(ty, base) \ + UPB_INLINE base *ty ## _upcast_mutable(ty *p) { return (base*)p; } \ + UPB_INLINE const base *ty ## _upcast(const ty *p) { return (const base*)p; } + +#define UPB_C_UPCASTS2(ty, base, base2) \ + UPB_C_UPCASTS(ty, base) \ + UPB_INLINE base2 *ty ## _upcast2_mutable(ty *p) { return (base2*)p; } \ + UPB_INLINE const base2 *ty ## _upcast2(const ty *p) { return (const base2*)p; } #ifdef __cplusplus -#define UPB_PRIVATE_FOR_CPP private: -#define UPB_DECLARE_TYPE(cppname, cname) typedef cppname cname; #define UPB_BEGIN_EXTERN_C extern "C" { #define UPB_END_EXTERN_C } -#define UPB_DEFINE_STRUCT0(cname, members) members; -#define UPB_DEFINE_STRUCT(cname, cbase, members) \ - public: \ - cbase* base() { return &base_; } \ - const cbase* base() const { return &base_; } \ - \ - private: \ - cbase base_; \ - members; -#define UPB_DEFINE_CLASS0(cppname, cppmethods, members) \ - class cppname { \ - cppmethods \ - members \ - }; \ - UPB_ASSERT_STDLAYOUT(cppname); -#define UPB_DEFINE_CLASS1(cppname, cppbase, cppmethods, members) \ - UPB_DEFINE_CLASS0(cppname, cppmethods, members) \ +#define UPB_PRIVATE_FOR_CPP private: +#define UPB_DECLARE_TYPE(cppname, cname) typedef cppname cname; + +#define UPB_DECLARE_DERIVED_TYPE(cppname, cppbase, cname, cbase) \ + UPB_DECLARE_TYPE(cppname, cname) \ + UPB_C_UPCASTS(cname, cbase) \ namespace upb { \ template <> \ class Pointer<cppname> : public PointerBase<cppname, cppbase> { \ @@ -183,8 +215,11 @@ explicit Pointer(const cppname* ptr) : PointerBase(ptr) {} \ }; \ } -#define UPB_DEFINE_CLASS2(cppname, cppbase, cppbase2, cppmethods, members) \ - UPB_DEFINE_CLASS0(cppname, UPB_QUOTE(cppmethods), members) \ + +#define UPB_DECLARE_DERIVED_TYPE2(cppname, cppbase, cppbase2, cname, cbase, \ + cbase2) \ + UPB_DECLARE_TYPE(cppname, cname) \ + UPB_C_UPCASTS2(cname, cbase, cbase2) \ namespace upb { \ template <> \ class Pointer<cppname> : public PointerBase2<cppname, cppbase, cppbase2> { \ @@ -199,96 +234,97 @@ }; \ } -#else // !defined(__cplusplus) +#else /* !defined(__cplusplus) */ +#define UPB_BEGIN_EXTERN_C +#define UPB_END_EXTERN_C #define UPB_PRIVATE_FOR_CPP #define UPB_DECLARE_TYPE(cppname, cname) \ struct cname; \ typedef struct cname cname; -#define UPB_BEGIN_EXTERN_C -#define UPB_END_EXTERN_C -#define UPB_DEFINE_STRUCT0(cname, members) \ - struct cname { \ - members; \ - }; -#define UPB_DEFINE_STRUCT(cname, cbase, members) \ - struct cname { \ - cbase base; \ - members; \ - }; -#define UPB_DEFINE_CLASS0(cppname, cppmethods, members) members -#define UPB_DEFINE_CLASS1(cppname, cppbase, cppmethods, members) members -#define UPB_DEFINE_CLASS2(cppname, cppbase, cppbase2, cppmethods, members) \ - members - -#endif // defined(__cplusplus) +#define UPB_DECLARE_DERIVED_TYPE(cppname, cppbase, cname, cbase) \ + UPB_DECLARE_TYPE(cppname, cname) \ + UPB_C_UPCASTS(cname, cbase) +#define UPB_DECLARE_DERIVED_TYPE2(cppname, cppbase, cppbase2, \ + cname, cbase, cbase2) \ + UPB_DECLARE_TYPE(cppname, cname) \ + UPB_C_UPCASTS2(cname, cbase, cbase2) -#ifdef __GNUC__ -#define UPB_NORETURN __attribute__((__noreturn__)) -#else -#define UPB_NORETURN -#endif +#endif /* defined(__cplusplus) */ #define UPB_MAX(x, y) ((x) > (y) ? (x) : (y)) #define UPB_MIN(x, y) ((x) < (y) ? (x) : (y)) #define UPB_UNUSED(var) (void)var -// Code with commas confuses the preprocessor when passed as arguments, whether -// C++ type names with commas (eg. Foo<int, int>) or code blocks that declare -// variables (ie. int foo, bar). -#define UPB_QUOTE(...) __VA_ARGS__ - -// For asserting something about a variable when the variable is not used for -// anything else. This prevents "unused variable" warnings when compiling in -// debug mode. +/* For asserting something about a variable when the variable is not used for + * anything else. This prevents "unused variable" warnings when compiling in + * debug mode. */ #define UPB_ASSERT_VAR(var, predicate) UPB_UNUSED(var); assert(predicate) -// Generic function type. +/* Generic function type. */ typedef void upb_func(); -/* Casts **********************************************************************/ - -// Upcasts for C. For downcasts see the definitions of the subtypes. -#define UPB_UPCAST(obj) (&(obj)->base) -#define UPB_UPCAST2(obj) UPB_UPCAST(UPB_UPCAST(obj)) +/* C++ Casts ******************************************************************/ #ifdef __cplusplus -// Downcasts for C++. We can't use C++ inheritance directly and maintain -// compatibility with C. So our inheritance is undeclared in C++. -// Specializations of these casting functions are defined for appropriate type -// pairs, and perform the necessary checks. -// -// Example: -// upb::Def* def = <...>; -// upb::MessageDef* = upb::dyn_cast<upb::MessageDef*>(def); - namespace upb { -// Casts to a direct subclass. The caller must know that cast is correct; an -// incorrect cast will throw an assertion failure in debug mode. +template <class T> class Pointer; + +/* Casts to a subclass. The caller must know that cast is correct; an + * incorrect cast will throw an assertion failure in debug mode. + * + * Example: + * upb::Def* def = GetDef(); + * // Assert-fails if this was not actually a MessageDef. + * upb::MessgeDef* md = upb::down_cast<upb::MessageDef>(def); + * + * Note that downcasts are only defined for some types (at the moment you can + * only downcast from a upb::Def to a specific Def type). */ template<class To, class From> To down_cast(From* f); -// Casts to a direct subclass. If the class does not actually match the given -// subtype, returns NULL. +/* Casts to a subclass. If the class does not actually match the given To type, + * returns NULL. + * + * Example: + * upb::Def* def = GetDef(); + * // md will be NULL if this was not actually a MessageDef. + * upb::MessgeDef* md = upb::down_cast<upb::MessageDef>(def); + * + * Note that dynamic casts are only defined for some types (at the moment you + * can only downcast from a upb::Def to a specific Def type).. */ template<class To, class From> To dyn_cast(From* f); -// Pointer<T> is a simple wrapper around a T*. It is only constructed for -// upcast() below, and its sole purpose is to be implicitly convertable to T* or -// pointers to base classes, just as a pointer would be in regular C++ if the -// inheritance were directly expressed as C++ inheritance. -template <class T> class Pointer; - -// Casts to any base class, or the type itself (ie. can be a no-op). +/* Casts to any base class, or the type itself (ie. can be a no-op). + * + * Example: + * upb::MessageDef* md = GetDef(); + * // This will fail to compile if this wasn't actually a base class. + * upb::Def* def = upb::upcast(md); + */ template <class T> inline Pointer<T> upcast(T *f) { return Pointer<T>(f); } +/* Attempt upcast to specific base class. + * + * Example: + * upb::MessageDef* md = GetDef(); + * upb::upcast_to<upb::Def>(md)->MethodOnDef(); + */ +template <class T, class F> inline T* upcast_to(F *f) { + return static_cast<T*>(upcast(f)); +} + +/* PointerBase<T>: implementation detail of upb::upcast(). + * It is implicitly convertable to pointers to the Base class(es). + */ template <class T, class Base> class PointerBase { public: explicit PointerBase(T* ptr) : ptr_(ptr) {} operator T*() { return ptr_; } - operator Base*() { return ptr_->base(); } + operator Base*() { return (Base*)ptr_; } private: T* ptr_; @@ -310,17 +346,17 @@ class PointerBase2 : public PointerBase<T, Base> { #ifdef __cplusplus -#include <algorithm> // For std::swap(). +#include <algorithm> /* For std::swap(). */ namespace upb { -// Provides RAII semantics for upb refcounted objects. Each reffed_ptr owns a -// ref on whatever object it points to (if any). +/* Provides RAII semantics for upb refcounted objects. Each reffed_ptr owns a + * ref on whatever object it points to (if any). */ template <class T> class reffed_ptr { public: reffed_ptr() : ptr_(NULL) {} - // If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. + /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */ template <class U> reffed_ptr(U* val, const void* ref_donor = NULL) : ptr_(upb::upcast(val)) { @@ -351,8 +387,8 @@ template <class T> class reffed_ptr { return *this; } - // TODO(haberman): add C++11 move construction/assignment for greater - // efficiency. + /* TODO(haberman): add C++11 move construction/assignment for greater + * efficiency. */ void swap(reffed_ptr& other) { if (ptr_ == other.ptr_) { @@ -376,7 +412,7 @@ template <class T> class reffed_ptr { T* get() const { return ptr_; } - // If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. + /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */ template <class U> void reset(U* ptr = NULL, const void* ref_donor = NULL) { reffed_ptr(ptr, ref_donor).swap(*this); @@ -392,8 +428,8 @@ template <class T> class reffed_ptr { return reffed_ptr<U>(upb::dyn_cast<U*>(get())); } - // Plain release() is unsafe; if we were the only owner, it would leak the - // object. Instead we provide this: + /* Plain release() is unsafe; if we were the only owner, it would leak the + * object. Instead we provide this: */ T* ReleaseTo(const void* new_owner) { T* ret = NULL; ptr_->DonateRef(this, new_owner); @@ -405,9 +441,9 @@ template <class T> class reffed_ptr { T* ptr_; }; -} // namespace upb +} /* namespace upb */ -#endif // __cplusplus +#endif /* __cplusplus */ /* upb::Status ****************************************************************/ @@ -419,70 +455,76 @@ class Status; } #endif -UPB_DECLARE_TYPE(upb::ErrorSpace, upb_errorspace); -UPB_DECLARE_TYPE(upb::Status, upb_status); +UPB_DECLARE_TYPE(upb::ErrorSpace, upb_errorspace) +UPB_DECLARE_TYPE(upb::Status, upb_status) -// The maximum length of an error message before it will get truncated. +/* The maximum length of an error message before it will get truncated. */ #define UPB_STATUS_MAX_MESSAGE 128 -// An error callback function is used to report errors from some component. -// The function can return "true" to indicate that the component should try -// to recover and proceed, but this is not always possible. +/* An error callback function is used to report errors from some component. + * The function can return "true" to indicate that the component should try + * to recover and proceed, but this is not always possible. */ typedef bool upb_errcb_t(void *closure, const upb_status* status); -UPB_DEFINE_CLASS0(upb::ErrorSpace, -, -UPB_DEFINE_STRUCT0(upb_errorspace, +#ifdef __cplusplus +class upb::ErrorSpace { +#else +struct upb_errorspace { +#endif const char *name; - // Should the error message in the status object according to this code. + /* Should the error message in the status object according to this code. */ void (*set_message)(upb_status* status, int code); -)); +}; -// Object representing a success or failure status. -// It owns no resources and allocates no memory, so it should work -// even in OOM situations. -UPB_DEFINE_CLASS0(upb::Status, +#ifdef __cplusplus + +/* Object representing a success or failure status. + * It owns no resources and allocates no memory, so it should work + * even in OOM situations. */ + +class upb::Status { public: Status(); - // Returns true if there is no error. + /* Returns true if there is no error. */ bool ok() const; - // Optional error space and code, useful if the caller wants to - // programmatically check the specific kind of error. + /* Optional error space and code, useful if the caller wants to + * programmatically check the specific kind of error. */ ErrorSpace* error_space(); int code() const; const char *error_message() const; - // The error message will be truncated if it is longer than - // UPB_STATUS_MAX_MESSAGE-4. + /* The error message will be truncated if it is longer than + * UPB_STATUS_MAX_MESSAGE-4. */ void SetErrorMessage(const char* msg); void SetFormattedErrorMessage(const char* fmt, ...); - // If there is no error message already, this will use the ErrorSpace to - // populate the error message for this code. The caller can still call - // SetErrorMessage() to give a more specific message. + /* If there is no error message already, this will use the ErrorSpace to + * populate the error message for this code. The caller can still call + * SetErrorMessage() to give a more specific message. */ void SetErrorCode(ErrorSpace* space, int code); - // Resets the status to a successful state with no message. + /* Resets the status to a successful state with no message. */ void Clear(); void CopyFrom(const Status& other); private: - UPB_DISALLOW_COPY_AND_ASSIGN(Status); -, -UPB_DEFINE_STRUCT0(upb_status, + UPB_DISALLOW_COPY_AND_ASSIGN(Status) +#else +struct upb_status { +#endif bool ok_; - // Specific status code defined by some error space (optional). + /* Specific status code defined by some error space (optional). */ int code_; upb_errorspace *error_space_; - // Error message; NULL-terminated. + /* Error message; NULL-terminated. */ char msg[UPB_STATUS_MAX_MESSAGE]; -)); +}; #define UPB_STATUS_INIT {true, 0, NULL, {0}} @@ -490,15 +532,15 @@ UPB_DEFINE_STRUCT0(upb_status, extern "C" { #endif -// The returned string is invalidated by any other call into the status. +/* The returned string is invalidated by any other call into the status. */ const char *upb_status_errmsg(const upb_status *status); bool upb_ok(const upb_status *status); upb_errorspace *upb_status_errspace(const upb_status *status); int upb_status_errcode(const upb_status *status); -// Any of the functions that write to a status object allow status to be NULL, -// to support use cases where the function's caller does not care about the -// status message. +/* Any of the functions that write to a status object allow status to be NULL, + * to support use cases where the function's caller does not care about the + * status message. */ void upb_status_clear(upb_status *status); void upb_status_seterrmsg(upb_status *status, const char *msg); void upb_status_seterrf(upb_status *status, const char *fmt, ...); @@ -507,11 +549,11 @@ void upb_status_seterrcode(upb_status *status, upb_errorspace *space, int code); void upb_status_copy(upb_status *to, const upb_status *from); #ifdef __cplusplus -} // extern "C" +} /* extern "C" */ namespace upb { -// C++ Wrappers +/* C++ Wrappers */ inline Status::Status() { Clear(); } inline bool Status::ok() const { return upb_ok(this); } inline const char* Status::error_message() const { @@ -534,7 +576,7 @@ inline void Status::CopyFrom(const Status& other) { upb_status_copy(this, &other); } -} // namespace upb +} /* namespace upb */ #endif @@ -547,9 +589,9 @@ extern "C" { /* upb_value ******************************************************************/ -// A tagged union (stored untagged inside the table) so that we can check that -// clients calling table accessors are correctly typed without having to have -// an explosion of accessors. +/* A tagged union (stored untagged inside the table) so that we can check that + * clients calling table accessors are correctly typed without having to have + * an explosion of accessors. */ typedef enum { UPB_CTYPE_INT32 = 1, UPB_CTYPE_INT64 = 2, @@ -559,85 +601,54 @@ typedef enum { UPB_CTYPE_CSTR = 6, UPB_CTYPE_PTR = 7, UPB_CTYPE_CONSTPTR = 8, - UPB_CTYPE_FPTR = 9, + UPB_CTYPE_FPTR = 9 } upb_ctype_t; -typedef union { - int32_t int32; - int64_t int64; - uint64_t uint64; - uint32_t uint32; - bool _bool; - char *cstr; - void *ptr; - const void *constptr; - upb_func *fptr; -} _upb_value; - typedef struct { - _upb_value val; + uint64_t val; #ifndef NDEBUG - // In debug mode we carry the value type around also so we can check accesses - // to be sure the right member is being read. + /* In debug mode we carry the value type around also so we can check accesses + * to be sure the right member is being read. */ upb_ctype_t ctype; #endif } upb_value; -#ifdef UPB_C99 -#define UPB_VALUE_INIT(v, member) {.member = v} -#endif -#define UPB__VALUE_INIT_NONE UPB_VALUE_INIT(NULL, ptr) - #ifdef NDEBUG #define SET_TYPE(dest, val) UPB_UNUSED(val) -#define UPB_VALUE_INIT_NONE {UPB__VALUE_INIT_NONE} #else #define SET_TYPE(dest, val) dest = val -// Non-existent type, all reads will fail. -#define UPB_VALUE_INIT_NONE {UPB__VALUE_INIT_NONE, -1} #endif -#define UPB_VALUE_INIT_INT32(v) UPB_VALUE_INIT(v, int32) -#define UPB_VALUE_INIT_INT64(v) UPB_VALUE_INIT(v, int64) -#define UPB_VALUE_INIT_UINT32(v) UPB_VALUE_INIT(v, uint32) -#define UPB_VALUE_INIT_UINT64(v) UPB_VALUE_INIT(v, uint64) -#define UPB_VALUE_INIT_BOOL(v) UPB_VALUE_INIT(v, _bool) -#define UPB_VALUE_INIT_CSTR(v) UPB_VALUE_INIT(v, cstr) -#define UPB_VALUE_INIT_PTR(v) UPB_VALUE_INIT(v, ptr) -#define UPB_VALUE_INIT_CONSTPTR(v) UPB_VALUE_INIT(v, constptr) -#define UPB_VALUE_INIT_FPTR(v) UPB_VALUE_INIT(v, fptr) - -// Like strdup(), which isn't always available since it's not ANSI C. +/* Like strdup(), which isn't always available since it's not ANSI C. */ char *upb_strdup(const char *s); -// Variant that works with a length-delimited rather than NULL-delimited string, -// as supported by strtable. +/* Variant that works with a length-delimited rather than NULL-delimited string, + * as supported by strtable. */ char *upb_strdup2(const char *s, size_t len); -UPB_INLINE void _upb_value_setval(upb_value *v, _upb_value val, +UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val, upb_ctype_t ctype) { v->val = val; SET_TYPE(v->ctype, ctype); } -UPB_INLINE upb_value _upb_value_val(_upb_value val, upb_ctype_t ctype) { +UPB_INLINE upb_value _upb_value_val(uint64_t val, upb_ctype_t ctype) { upb_value ret; _upb_value_setval(&ret, val, ctype); return ret; } -// For each value ctype, define the following set of functions: -// -// // Get/set an int32 from a upb_value. -// int32_t upb_value_getint32(upb_value val); -// void upb_value_setint32(upb_value *val, int32_t cval); -// -// // Construct a new upb_value from an int32. -// upb_value upb_value_int32(int32_t val); -#define FUNCS(name, membername, type_t, proto_type) \ +/* For each value ctype, define the following set of functions: + * + * // Get/set an int32 from a upb_value. + * int32_t upb_value_getint32(upb_value val); + * void upb_value_setint32(upb_value *val, int32_t cval); + * + * // Construct a new upb_value from an int32. + * upb_value upb_value_int32(int32_t val); */ +#define FUNCS(name, membername, type_t, converter, proto_type) \ UPB_INLINE void upb_value_set ## name(upb_value *val, type_t cval) { \ - val->val.uint64 = 0; \ + val->val = (converter)cval; \ SET_TYPE(val->ctype, proto_type); \ - val->val.membername = cval; \ } \ UPB_INLINE upb_value upb_value_ ## name(type_t val) { \ upb_value ret; \ @@ -646,69 +657,148 @@ UPB_INLINE upb_value _upb_value_val(_upb_value val, upb_ctype_t ctype) { } \ UPB_INLINE type_t upb_value_get ## name(upb_value val) { \ assert(val.ctype == proto_type); \ - return val.val.membername; \ + return (type_t)(converter)val.val; \ } -FUNCS(int32, int32, int32_t, UPB_CTYPE_INT32); -FUNCS(int64, int64, int64_t, UPB_CTYPE_INT64); -FUNCS(uint32, uint32, uint32_t, UPB_CTYPE_UINT32); -FUNCS(uint64, uint64, uint64_t, UPB_CTYPE_UINT64); -FUNCS(bool, _bool, bool, UPB_CTYPE_BOOL); -FUNCS(cstr, cstr, char*, UPB_CTYPE_CSTR); -FUNCS(ptr, ptr, void*, UPB_CTYPE_PTR); -FUNCS(constptr, constptr, const void*, UPB_CTYPE_CONSTPTR); -FUNCS(fptr, fptr, upb_func*, UPB_CTYPE_FPTR); +FUNCS(int32, int32, int32_t, int32_t, UPB_CTYPE_INT32) +FUNCS(int64, int64, int64_t, int64_t, UPB_CTYPE_INT64) +FUNCS(uint32, uint32, uint32_t, uint32_t, UPB_CTYPE_UINT32) +FUNCS(uint64, uint64, uint64_t, uint64_t, UPB_CTYPE_UINT64) +FUNCS(bool, _bool, bool, bool, UPB_CTYPE_BOOL) +FUNCS(cstr, cstr, char*, uintptr_t, UPB_CTYPE_CSTR) +FUNCS(ptr, ptr, void*, uintptr_t, UPB_CTYPE_PTR) +FUNCS(constptr, constptr, const void*, uintptr_t, UPB_CTYPE_CONSTPTR) +FUNCS(fptr, fptr, upb_func*, uintptr_t, UPB_CTYPE_FPTR) #undef FUNCS +#undef SET_TYPE -/* upb_table ******************************************************************/ +/* upb_tabkey *****************************************************************/ + +/* Either: + * 1. an actual integer key, or + * 2. a pointer to a string prefixed by its uint32_t length, owned by us. + * + * ...depending on whether this is a string table or an int table. We would + * make this a union of those two types, but C89 doesn't support statically + * initializing a non-first union member. */ +typedef uintptr_t upb_tabkey; + +#define UPB_TABKEY_NUM(n) n +#define UPB_TABKEY_NONE 0 +/* The preprocessor isn't quite powerful enough to turn the compile-time string + * length into a byte-wise string representation, so code generation needs to + * help it along. + * + * "len1" is the low byte and len4 is the high byte. */ +#ifdef UPB_BIG_ENDIAN +#define UPB_TABKEY_STR(len1, len2, len3, len4, strval) \ + (uintptr_t)(len4 len3 len2 len1 strval) +#else +#define UPB_TABKEY_STR(len1, len2, len3, len4, strval) \ + (uintptr_t)(len1 len2 len3 len4 strval) +#endif + +UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) { + char* mem = (char*)key; + if (len) memcpy(len, mem, sizeof(*len)); + return mem + sizeof(*len); +} + + +/* upb_tabval *****************************************************************/ + +#ifdef __cplusplus + +/* Status initialization not supported. + * + * This separate definition is necessary because in C++, UINTPTR_MAX isn't + * reliably available. */ +typedef struct { + uint64_t val; +} upb_tabval; + +#else + +/* C -- supports static initialization, but to support static initialization of + * both integers and points for both 32 and 64 bit targets, it takes a little + * bit of doing. */ + +#if UINTPTR_MAX == 0xffffffffffffffffULL +#define UPB_PTR_IS_64BITS +#elif UINTPTR_MAX != 0xffffffff +#error Could not determine how many bits pointers are. +#endif typedef union { - uintptr_t num; + /* For static initialization. + * + * Unfortunately this ugliness is necessary -- it is the only way that we can, + * with -std=c89 -pedantic, statically initialize this to either a pointer or + * an integer on 32-bit platforms. */ struct { - // We own this. NULL-terminated but may also contain binary data; see - // explicit length below. - // TODO: move the length to the start of the string in order to reduce - // tabkey's size (to one machine word) in a way that supports static - // initialization. - const char *str; - size_t length; - } s; -} upb_tabkey; - -#define UPB_TABKEY_NUM(n) {n} -#ifdef UPB_C99 -// Given that |s| is a string literal, sizeof(s) gives us a -// compile-time-constant strlen(). We must ensure that this works for static -// data initializers. -#define UPB_TABKEY_STR(strval) { .s = { .str = strval, \ - .length = sizeof(strval) - 1 } } +#ifdef UPB_PTR_IS_64BITS + uintptr_t val; +#else + uintptr_t val1; + uintptr_t val2; +#endif + } staticinit; + + /* The normal accessor that we use for everything at runtime. */ + uint64_t val; +} upb_tabval; + +#ifdef UPB_PTR_IS_64BITS +#define UPB_TABVALUE_INT_INIT(v) {{v}} +#define UPB_TABVALUE_EMPTY_INIT {{-1}} +#else + +/* 32-bit pointers */ + +#ifdef UPB_BIG_ENDIAN +#define UPB_TABVALUE_INT_INIT(v) {{0, v}} +#define UPB_TABVALUE_EMPTY_INIT {{-1, -1}} +#else +#define UPB_TABVALUE_INT_INIT(v) {{v, 0}} +#define UPB_TABVALUE_EMPTY_INIT {{-1, -1}} +#endif + #endif -// TODO(haberman): C++ -#define UPB_TABKEY_NONE {0} + +#define UPB_TABVALUE_PTR_INIT(v) UPB_TABVALUE_INT_INIT((uintptr_t)v) + +#undef UPB_PTR_IS_64BITS + +#endif /* __cplusplus */ + + +/* upb_table ******************************************************************/ typedef struct _upb_tabent { upb_tabkey key; - _upb_value val; - // Internal chaining. This is const so we can create static initializers for - // tables. We cast away const sometimes, but *only* when the containing - // upb_table is known to be non-const. This requires a bit of care, but - // the subtlety is confined to table.c. + upb_tabval val; + + /* Internal chaining. This is const so we can create static initializers for + * tables. We cast away const sometimes, but *only* when the containing + * upb_table is known to be non-const. This requires a bit of care, but + * the subtlety is confined to table.c. */ const struct _upb_tabent *next; } upb_tabent; typedef struct { - size_t count; // Number of entries in the hash part. - size_t mask; // Mask to turn hash value -> bucket. - upb_ctype_t ctype; // Type of all values. - uint8_t size_lg2; // Size of the hash table part is 2^size_lg2 entries. - - // Hash table entries. - // Making this const isn't entirely accurate; what we really want is for it to - // have the same const-ness as the table it's inside. But there's no way to - // declare that in C. So we have to make it const so that we can statically - // initialize const hash tables. Then we cast away const when we have to. + size_t count; /* Number of entries in the hash part. */ + size_t mask; /* Mask to turn hash value -> bucket. */ + upb_ctype_t ctype; /* Type of all values. */ + uint8_t size_lg2; /* Size of the hashtable part is 2^size_lg2 entries. */ + + /* Hash table entries. + * Making this const isn't entirely accurate; what we really want is for it to + * have the same const-ness as the table it's inside. But there's no way to + * declare that in C. So we have to make it const so that we can statically + * initialize const hash tables. Then we cast away const when we have to. + */ const upb_tabent *entries; } upb_table; @@ -723,10 +813,10 @@ typedef struct { UPB_STRTABLE_INIT(0, 0, ctype, 0, NULL) typedef struct { - upb_table t; // For entries that don't fit in the array part. - const _upb_value *array; // Array part of the table. See const note above. - size_t array_size; // Array part size. - size_t array_count; // Array part number of elements. + upb_table t; /* For entries that don't fit in the array part. */ + const upb_tabval *array; /* Array part of the table. See const note above. */ + size_t array_size; /* Array part size. */ + size_t array_count; /* Array part number of elements. */ } upb_inttable; #define UPB_INTTABLE_INIT(count, mask, ctype, size_lg2, ent, a, asize, acount) \ @@ -735,8 +825,7 @@ typedef struct { #define UPB_EMPTY_INTTABLE_INIT(ctype) \ UPB_INTTABLE_INIT(0, 0, ctype, 0, NULL, NULL, 0, 0) -#define UPB_ARRAY_EMPTYVAL -1 -#define UPB_ARRAY_EMPTYENT UPB_VALUE_INIT_INT64(UPB_ARRAY_EMPTYVAL) +#define UPB_ARRAY_EMPTYENT -1 UPB_INLINE size_t upb_table_size(const upb_table *t) { if (t->size_lg2 == 0) @@ -745,18 +834,16 @@ UPB_INLINE size_t upb_table_size(const upb_table *t) { return 1 << t->size_lg2; } -// Internal-only functions, in .h file only out of necessity. +/* Internal-only functions, in .h file only out of necessity. */ UPB_INLINE bool upb_tabent_isempty(const upb_tabent *e) { - return e->key.num == 0; + return e->key == 0; } -// Used by some of the unit tests for generic hashing functionality. +/* Used by some of the unit tests for generic hashing functionality. */ uint32_t MurmurHash2(const void * key, size_t len, uint32_t seed); -UPB_INLINE upb_tabkey upb_intkey(uintptr_t key) { - upb_tabkey k; - k.num = key; - return k; +UPB_INLINE uintptr_t upb_intkey(uintptr_t key) { + return key; } UPB_INLINE uint32_t upb_inthash(uintptr_t key) { @@ -767,93 +854,94 @@ static const upb_tabent *upb_getentry(const upb_table *t, uint32_t hash) { return t->entries + (hash & t->mask); } -UPB_INLINE bool upb_arrhas(_upb_value v) { - return v.uint64 != (uint64_t)UPB_ARRAY_EMPTYVAL; +UPB_INLINE bool upb_arrhas(upb_tabval key) { + return key.val != (uint64_t)-1; } -// Initialize and uninitialize a table, respectively. If memory allocation -// failed, false is returned that the table is uninitialized. +/* Initialize and uninitialize a table, respectively. If memory allocation + * failed, false is returned that the table is uninitialized. */ bool upb_inttable_init(upb_inttable *table, upb_ctype_t ctype); bool upb_strtable_init(upb_strtable *table, upb_ctype_t ctype); void upb_inttable_uninit(upb_inttable *table); void upb_strtable_uninit(upb_strtable *table); -// Returns the number of values in the table. +/* Returns the number of values in the table. */ size_t upb_inttable_count(const upb_inttable *t); UPB_INLINE size_t upb_strtable_count(const upb_strtable *t) { return t->t.count; } -// Inserts the given key into the hashtable with the given value. The key must -// not already exist in the hash table. For string tables, the key must be -// NULL-terminated, and the table will make an internal copy of the key. -// Inttables must not insert a value of UINTPTR_MAX. -// -// If a table resize was required but memory allocation failed, false is -// returned and the table is unchanged. +/* Inserts the given key into the hashtable with the given value. The key must + * not already exist in the hash table. For string tables, the key must be + * NULL-terminated, and the table will make an internal copy of the key. + * Inttables must not insert a value of UINTPTR_MAX. + * + * If a table resize was required but memory allocation failed, false is + * returned and the table is unchanged. */ bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val); bool upb_strtable_insert2(upb_strtable *t, const char *key, size_t len, upb_value val); -// For NULL-terminated strings. +/* For NULL-terminated strings. */ UPB_INLINE bool upb_strtable_insert(upb_strtable *t, const char *key, upb_value val) { return upb_strtable_insert2(t, key, strlen(key), val); } -// Looks up key in this table, returning "true" if the key was found. -// If v is non-NULL, copies the value for this key into *v. +/* Looks up key in this table, returning "true" if the key was found. + * If v is non-NULL, copies the value for this key into *v. */ bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v); bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len, upb_value *v); -// For NULL-terminated strings. +/* For NULL-terminated strings. */ UPB_INLINE bool upb_strtable_lookup(const upb_strtable *t, const char *key, upb_value *v) { return upb_strtable_lookup2(t, key, strlen(key), v); } -// Removes an item from the table. Returns true if the remove was successful, -// and stores the removed item in *val if non-NULL. +/* Removes an item from the table. Returns true if the remove was successful, + * and stores the removed item in *val if non-NULL. */ bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val); bool upb_strtable_remove2(upb_strtable *t, const char *key, size_t len, upb_value *val); -// For NULL-terminated strings. +/* For NULL-terminated strings. */ UPB_INLINE bool upb_strtable_remove(upb_strtable *t, const char *key, upb_value *v) { return upb_strtable_remove2(t, key, strlen(key), v); } -// Updates an existing entry in an inttable. If the entry does not exist, -// returns false and does nothing. Unlike insert/remove, this does not -// invalidate iterators. +/* Updates an existing entry in an inttable. If the entry does not exist, + * returns false and does nothing. Unlike insert/remove, this does not + * invalidate iterators. */ bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val); -// Handy routines for treating an inttable like a stack. May not be mixed with -// other insert/remove calls. +/* Handy routines for treating an inttable like a stack. May not be mixed with + * other insert/remove calls. */ bool upb_inttable_push(upb_inttable *t, upb_value val); upb_value upb_inttable_pop(upb_inttable *t); -// Convenience routines for inttables with pointer keys. +/* Convenience routines for inttables with pointer keys. */ bool upb_inttable_insertptr(upb_inttable *t, const void *key, upb_value val); bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val); bool upb_inttable_lookupptr( const upb_inttable *t, const void *key, upb_value *val); -// Optimizes the table for the current set of entries, for both memory use and -// lookup time. Client should call this after all entries have been inserted; -// inserting more entries is legal, but will likely require a table resize. +/* Optimizes the table for the current set of entries, for both memory use and + * lookup time. Client should call this after all entries have been inserted; + * inserting more entries is legal, but will likely require a table resize. */ void upb_inttable_compact(upb_inttable *t); -// A special-case inlinable version of the lookup routine for 32-bit integers. +/* A special-case inlinable version of the lookup routine for 32-bit + * integers. */ UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key, upb_value *v) { - *v = upb_value_int32(0); // Silence compiler warnings. + *v = upb_value_int32(0); /* Silence compiler warnings. */ if (key < t->array_size) { - _upb_value arrval = t->array[key]; + upb_tabval arrval = t->array[key]; if (upb_arrhas(arrval)) { - _upb_value_setval(v, arrval, t->t.ctype); + _upb_value_setval(v, arrval.val, t->t.ctype); return true; } else { return false; @@ -862,8 +950,8 @@ UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key, const upb_tabent *e; if (t->t.entries == NULL) return false; for (e = upb_getentry(&t->t, upb_inthash(key)); true; e = e->next) { - if ((uint32_t)e->key.num == key) { - _upb_value_setval(v, e->val, t->t.ctype); + if ((uint32_t)e->key == key) { + _upb_value_setval(v, e->val.val, t->t.ctype); return true; } if (e->next == NULL) return false; @@ -871,42 +959,43 @@ UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key, } } -// Exposed for testing only. +/* Exposed for testing only. */ bool upb_strtable_resize(upb_strtable *t, size_t size_lg2); /* Iterators ******************************************************************/ -// Iterators for int and string tables. We are subject to some kind of unusual -// design constraints: -// -// For high-level languages: -// - we must be able to guarantee that we don't crash or corrupt memory even if -// the program accesses an invalidated iterator. -// -// For C++11 range-based for: -// - iterators must be copyable -// - iterators must be comparable -// - it must be possible to construct an "end" value. -// -// Iteration order is undefined. -// -// Modifying the table invalidates iterators. upb_{str,int}table_done() is -// guaranteed to work even on an invalidated iterator, as long as the table it -// is iterating over has not been freed. Calling next() or accessing data from -// an invalidated iterator yields unspecified elements from the table, but it is -// guaranteed not to crash and to return real table elements (except when done() -// is true). +/* Iterators for int and string tables. We are subject to some kind of unusual + * design constraints: + * + * For high-level languages: + * - we must be able to guarantee that we don't crash or corrupt memory even if + * the program accesses an invalidated iterator. + * + * For C++11 range-based for: + * - iterators must be copyable + * - iterators must be comparable + * - it must be possible to construct an "end" value. + * + * Iteration order is undefined. + * + * Modifying the table invalidates iterators. upb_{str,int}table_done() is + * guaranteed to work even on an invalidated iterator, as long as the table it + * is iterating over has not been freed. Calling next() or accessing data from + * an invalidated iterator yields unspecified elements from the table, but it is + * guaranteed not to crash and to return real table elements (except when done() + * is true). */ /* upb_strtable_iter **********************************************************/ -// upb_strtable_iter i; -// upb_strtable_begin(&i, t); -// for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { -// const char *key = upb_strtable_iter_key(&i); -// const upb_value val = upb_strtable_iter_value(&i); -// // ... -// } +/* upb_strtable_iter i; + * upb_strtable_begin(&i, t); + * for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { + * const char *key = upb_strtable_iter_key(&i); + * const upb_value val = upb_strtable_iter_value(&i); + * // ... + * } + */ typedef struct { const upb_strtable *t; @@ -926,13 +1015,14 @@ bool upb_strtable_iter_isequal(const upb_strtable_iter *i1, /* upb_inttable_iter **********************************************************/ -// upb_inttable_iter i; -// upb_inttable_begin(&i, t); -// for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { -// uintptr_t key = upb_inttable_iter_key(&i); -// upb_value val = upb_inttable_iter_value(&i); -// // ... -// } +/* upb_inttable_iter i; + * upb_inttable_begin(&i, t); + * for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { + * uintptr_t key = upb_inttable_iter_key(&i); + * upb_value val = upb_inttable_iter_value(&i); + * // ... + * } + */ typedef struct { const upb_inttable *t; @@ -956,84 +1046,102 @@ bool upb_inttable_iter_isequal(const upb_inttable_iter *i1, #endif /* UPB_TABLE_H_ */ -// Reference tracking will check ref()/unref() operations to make sure the -// ref ownership is correct. Where possible it will also make tools like -// Valgrind attribute ref leaks to the code that took the leaked ref, not -// the code that originally created the object. -// -// Enabling this requires the application to define upb_lock()/upb_unlock() -// functions that acquire/release a global mutex (or #define UPB_THREAD_UNSAFE). -#ifndef NDEBUG -#define UPB_DEBUG_REFS -#endif +/* Reference tracking will check ref()/unref() operations to make sure the + * ref ownership is correct. Where possible it will also make tools like + * Valgrind attribute ref leaks to the code that took the leaked ref, not + * the code that originally created the object. + * + * Enabling this requires the application to define upb_lock()/upb_unlock() + * functions that acquire/release a global mutex (or #define UPB_THREAD_UNSAFE). + * For this reason we don't enable it by default, even in debug builds. + */ + +/* #define UPB_DEBUG_REFS */ #ifdef __cplusplus namespace upb { class RefCounted; } #endif -UPB_DECLARE_TYPE(upb::RefCounted, upb_refcounted); +UPB_DECLARE_TYPE(upb::RefCounted, upb_refcounted) struct upb_refcounted_vtbl; -UPB_DEFINE_CLASS0(upb::RefCounted, +#ifdef __cplusplus + +class upb::RefCounted { public: - // Returns true if the given object is frozen. + /* Returns true if the given object is frozen. */ bool IsFrozen() const; - // Increases the ref count, the new ref is owned by "owner" which must not - // already own a ref (and should not itself be a refcounted object if the ref - // could possibly be circular; see below). - // Thread-safe iff "this" is frozen. + /* Increases the ref count, the new ref is owned by "owner" which must not + * already own a ref (and should not itself be a refcounted object if the ref + * could possibly be circular; see below). + * Thread-safe iff "this" is frozen. */ void Ref(const void *owner) const; - // Release a ref that was acquired from upb_refcounted_ref() and collects any - // objects it can. + /* Release a ref that was acquired from upb_refcounted_ref() and collects any + * objects it can. */ void Unref(const void *owner) const; - // Moves an existing ref from "from" to "to", without changing the overall - // ref count. DonateRef(foo, NULL, owner) is the same as Ref(foo, owner), - // but "to" may not be NULL. + /* Moves an existing ref from "from" to "to", without changing the overall + * ref count. DonateRef(foo, NULL, owner) is the same as Ref(foo, owner), + * but "to" may not be NULL. */ void DonateRef(const void *from, const void *to) const; - // Verifies that a ref to the given object is currently held by the given - // owner. Only effective in UPB_DEBUG_REFS builds. + /* Verifies that a ref to the given object is currently held by the given + * owner. Only effective in UPB_DEBUG_REFS builds. */ void CheckRef(const void *owner) const; private: - UPB_DISALLOW_POD_OPS(RefCounted, upb::RefCounted); -, -UPB_DEFINE_STRUCT0(upb_refcounted, - // A single reference count shared by all objects in the group. + UPB_DISALLOW_POD_OPS(RefCounted, upb::RefCounted) +#else +struct upb_refcounted { +#endif + /* TODO(haberman): move the actual structure definition to structdefs.int.h. + * The only reason they are here is because inline functions need to see the + * definition of upb_handlers, which needs to see this definition. But we + * can change the upb_handlers inline functions to deal in raw offsets + * instead. + */ + + /* A single reference count shared by all objects in the group. */ uint32_t *group; - // A singly-linked list of all objects in the group. + /* A singly-linked list of all objects in the group. */ upb_refcounted *next; - // Table of function pointers for this type. + /* Table of function pointers for this type. */ const struct upb_refcounted_vtbl *vtbl; - // Maintained only when mutable, this tracks the number of refs (but not - // ref2's) to this object. *group should be the sum of all individual_count - // in the group. + /* Maintained only when mutable, this tracks the number of refs (but not + * ref2's) to this object. *group should be the sum of all individual_count + * in the group. */ uint32_t individual_count; bool is_frozen; #ifdef UPB_DEBUG_REFS - upb_inttable *refs; // Maps owner -> trackedref for incoming refs. - upb_inttable *ref2s; // Set of targets for outgoing ref2s. + upb_inttable *refs; /* Maps owner -> trackedref for incoming refs. */ + upb_inttable *ref2s; /* Set of targets for outgoing ref2s. */ +#endif +}; + +#ifdef UPB_DEBUG_REFS +#define UPB_REFCOUNT_INIT(refs, ref2s) \ + {&static_refcount, NULL, NULL, 0, true, refs, ref2s} +#else +#define UPB_REFCOUNT_INIT(refs, ref2s) {&static_refcount, NULL, NULL, 0, true} #endif -)); -UPB_BEGIN_EXTERN_C // { +UPB_BEGIN_EXTERN_C -// It is better to use tracked refs when possible, for the extra debugging -// capability. But if this is not possible (because you don't have easy access -// to a stable pointer value that is associated with the ref), you can pass -// UPB_UNTRACKED_REF instead. +/* It is better to use tracked refs when possible, for the extra debugging + * capability. But if this is not possible (because you don't have easy access + * to a stable pointer value that is associated with the ref), you can pass + * UPB_UNTRACKED_REF instead. */ extern const void *UPB_UNTRACKED_REF; -// Native C API. +/* Native C API. */ bool upb_refcounted_isfrozen(const upb_refcounted *r); void upb_refcounted_ref(const upb_refcounted *r, const void *owner); void upb_refcounted_unref(const upb_refcounted *r, const void *owner); @@ -1041,37 +1149,70 @@ void upb_refcounted_donateref( const upb_refcounted *r, const void *from, const void *to); void upb_refcounted_checkref(const upb_refcounted *r, const void *owner); +#define UPB_REFCOUNTED_CMETHODS(type, upcastfunc) \ + UPB_INLINE bool type ## _isfrozen(const type *v) { \ + return upb_refcounted_isfrozen(upcastfunc(v)); \ + } \ + UPB_INLINE void type ## _ref(const type *v, const void *owner) { \ + upb_refcounted_ref(upcastfunc(v), owner); \ + } \ + UPB_INLINE void type ## _unref(const type *v, const void *owner) { \ + upb_refcounted_unref(upcastfunc(v), owner); \ + } \ + UPB_INLINE void type ## _donateref(const type *v, const void *from, const void *to) { \ + upb_refcounted_donateref(upcastfunc(v), from, to); \ + } \ + UPB_INLINE void type ## _checkref(const type *v, const void *owner) { \ + upb_refcounted_checkref(upcastfunc(v), owner); \ + } -// Internal-to-upb Interface /////////////////////////////////////////////////// +#define UPB_REFCOUNTED_CPPMETHODS \ + bool IsFrozen() const { \ + return upb::upcast_to<const upb::RefCounted>(this)->IsFrozen(); \ + } \ + void Ref(const void *owner) const { \ + return upb::upcast_to<const upb::RefCounted>(this)->Ref(owner); \ + } \ + void Unref(const void *owner) const { \ + return upb::upcast_to<const upb::RefCounted>(this)->Unref(owner); \ + } \ + void DonateRef(const void *from, const void *to) const { \ + return upb::upcast_to<const upb::RefCounted>(this)->DonateRef(from, to); \ + } \ + void CheckRef(const void *owner) const { \ + return upb::upcast_to<const upb::RefCounted>(this)->CheckRef(owner); \ + } + +/* Internal-to-upb Interface **************************************************/ typedef void upb_refcounted_visit(const upb_refcounted *r, const upb_refcounted *subobj, void *closure); struct upb_refcounted_vtbl { - // Must visit all subobjects that are currently ref'd via upb_refcounted_ref2. - // Must be longjmp()-safe. + /* Must visit all subobjects that are currently ref'd via upb_refcounted_ref2. + * Must be longjmp()-safe. */ void (*visit)(const upb_refcounted *r, upb_refcounted_visit *visit, void *c); - // Must free the object and release all references to other objects. + /* Must free the object and release all references to other objects. */ void (*free)(upb_refcounted *r); }; -// Initializes the refcounted with a single ref for the given owner. Returns -// false if memory could not be allocated. +/* Initializes the refcounted with a single ref for the given owner. Returns + * false if memory could not be allocated. */ bool upb_refcounted_init(upb_refcounted *r, const struct upb_refcounted_vtbl *vtbl, const void *owner); -// Adds a ref from one refcounted object to another ("from" must not already -// own a ref). These refs may be circular; cycles will be collected correctly -// (if conservatively). These refs do not need to be freed in from's free() -// function. +/* Adds a ref from one refcounted object to another ("from" must not already + * own a ref). These refs may be circular; cycles will be collected correctly + * (if conservatively). These refs do not need to be freed in from's free() + * function. */ void upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from); -// Removes a ref that was acquired from upb_refcounted_ref2(), and collects any -// object it can. This is only necessary when "from" no longer points to "r", -// and not from from's "free" function. +/* Removes a ref that was acquired from upb_refcounted_ref2(), and collects any + * object it can. This is only necessary when "from" no longer points to "r", + * and not from from's "free" function. */ void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from); #define upb_ref2(r, from) \ @@ -1079,37 +1220,30 @@ void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from); #define upb_unref2(r, from) \ upb_refcounted_unref2((const upb_refcounted*)r, (upb_refcounted*)from) -// Freezes all mutable object reachable by ref2() refs from the given roots. -// This will split refcounting groups into precise SCC groups, so that -// refcounting of frozen objects can be more aggressive. If memory allocation -// fails, or if more than 2**31 mutable objects are reachable from "roots", or -// if the maximum depth of the graph exceeds "maxdepth", false is returned and -// the objects are unchanged. -// -// After this operation succeeds, the objects are frozen/const, and may not be -// used through non-const pointers. In particular, they may not be passed as -// the second parameter of upb_refcounted_{ref,unref}2(). On the upside, all -// operations on frozen refcounteds are threadsafe, and objects will be freed -// at the precise moment that they become unreachable. -// -// Caller must own refs on each object in the "roots" list. +/* Freezes all mutable object reachable by ref2() refs from the given roots. + * This will split refcounting groups into precise SCC groups, so that + * refcounting of frozen objects can be more aggressive. If memory allocation + * fails, or if more than 2**31 mutable objects are reachable from "roots", or + * if the maximum depth of the graph exceeds "maxdepth", false is returned and + * the objects are unchanged. + * + * After this operation succeeds, the objects are frozen/const, and may not be + * used through non-const pointers. In particular, they may not be passed as + * the second parameter of upb_refcounted_{ref,unref}2(). On the upside, all + * operations on frozen refcounteds are threadsafe, and objects will be freed + * at the precise moment that they become unreachable. + * + * Caller must own refs on each object in the "roots" list. */ bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s, int maxdepth); -// Shared by all compiled-in refcounted objects. +/* Shared by all compiled-in refcounted objects. */ extern uint32_t static_refcount; -UPB_END_EXTERN_C // } - -#ifdef UPB_DEBUG_REFS -#define UPB_REFCOUNT_INIT(refs, ref2s) \ - {&static_refcount, NULL, NULL, 0, true, refs, ref2s} -#else -#define UPB_REFCOUNT_INIT(refs, ref2s) {&static_refcount, NULL, NULL, 0, true} -#endif +UPB_END_EXTERN_C #ifdef __cplusplus -// C++ Wrappers. +/* C++ Wrappers. */ namespace upb { inline bool RefCounted::IsFrozen() const { return upb_refcounted_isfrozen(this); @@ -1126,10 +1260,10 @@ inline void RefCounted::DonateRef(const void *from, const void *to) const { inline void RefCounted::CheckRef(const void *owner) const { upb_refcounted_checkref(this, owner); } -} // namespace upb +} /* namespace upb */ #endif -#endif // UPB_REFCOUNT_H_ +#endif /* UPB_REFCOUNT_H_ */ #ifdef __cplusplus #include <cstring> @@ -1145,114 +1279,90 @@ class OneofDef; } #endif -UPB_DECLARE_TYPE(upb::Def, upb_def); -UPB_DECLARE_TYPE(upb::EnumDef, upb_enumdef); -UPB_DECLARE_TYPE(upb::FieldDef, upb_fielddef); -UPB_DECLARE_TYPE(upb::MessageDef, upb_msgdef); -UPB_DECLARE_TYPE(upb::OneofDef, upb_oneofdef); - -// Maximum field number allowed for FieldDefs. This is an inherent limit of the -// protobuf wire format. -#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1) +UPB_DECLARE_DERIVED_TYPE(upb::Def, upb::RefCounted, upb_def, upb_refcounted) -// The maximum message depth that the type graph can have. This is a resource -// limit for the C stack since we sometimes need to recursively traverse the -// graph. Cycles are ok; the traversal will stop when it detects a cycle, but -// we must hit the cycle before the maximum depth is reached. -// -// If having a single static limit is too inflexible, we can add another variant -// of Def::Freeze that allows specifying this as a parameter. +/* The maximum message depth that the type graph can have. This is a resource + * limit for the C stack since we sometimes need to recursively traverse the + * graph. Cycles are ok; the traversal will stop when it detects a cycle, but + * we must hit the cycle before the maximum depth is reached. + * + * If having a single static limit is too inflexible, we can add another variant + * of Def::Freeze that allows specifying this as a parameter. */ #define UPB_MAX_MESSAGE_DEPTH 64 /* upb::Def: base class for defs *********************************************/ -// All the different kind of defs we support. These correspond 1:1 with -// declarations in a .proto file. +/* All the different kind of defs we support. These correspond 1:1 with + * declarations in a .proto file. */ typedef enum { UPB_DEF_MSG, UPB_DEF_FIELD, UPB_DEF_ENUM, UPB_DEF_ONEOF, - UPB_DEF_SERVICE, // Not yet implemented. - UPB_DEF_ANY = -1, // Wildcard for upb_symtab_get*() + UPB_DEF_SERVICE, /* Not yet implemented. */ + UPB_DEF_ANY = -1 /* Wildcard for upb_symtab_get*() */ } upb_deftype_t; -// The base class of all defs. Its base is upb::RefCounted (use upb::upcast() -// to convert). -UPB_DEFINE_CLASS1(upb::Def, upb::RefCounted, +#ifdef __cplusplus + +/* The base class of all defs. Its base is upb::RefCounted (use upb::upcast() + * to convert). */ +class upb::Def { public: typedef upb_deftype_t Type; Def* Dup(const void *owner) const; - // Functionality from upb::RefCounted. - bool IsFrozen() const; - void Ref(const void* owner) const; - void Unref(const void* owner) const; - void DonateRef(const void* from, const void* to) const; - void CheckRef(const void* owner) const; + /* upb::RefCounted methods like Ref()/Unref(). */ + UPB_REFCOUNTED_CPPMETHODS Type def_type() const; - // "fullname" is the def's fully-qualified name (eg. foo.bar.Message). + /* "fullname" is the def's fully-qualified name (eg. foo.bar.Message). */ const char *full_name() const; - // The def must be mutable. Caller retains ownership of fullname. Defs are - // not required to have a name; if a def has no name when it is frozen, it - // will remain an anonymous def. On failure, returns false and details in "s" - // if non-NULL. + /* The def must be mutable. Caller retains ownership of fullname. Defs are + * not required to have a name; if a def has no name when it is frozen, it + * will remain an anonymous def. On failure, returns false and details in "s" + * if non-NULL. */ bool set_full_name(const char* fullname, upb::Status* s); bool set_full_name(const std::string &fullname, upb::Status* s); - // Freezes the given defs; this validates all constraints and marks the defs - // as frozen (read-only). "defs" may not contain any fielddefs, but fields - // of any msgdefs will be frozen. - // - // Symbolic references to sub-types and enum defaults must have already been - // resolved. Any mutable defs reachable from any of "defs" must also be in - // the list; more formally, "defs" must be a transitive closure of mutable - // defs. - // - // After this operation succeeds, the finalized defs must only be accessed - // through a const pointer! + /* Freezes the given defs; this validates all constraints and marks the defs + * as frozen (read-only). "defs" may not contain any fielddefs, but fields + * of any msgdefs will be frozen. + * + * Symbolic references to sub-types and enum defaults must have already been + * resolved. Any mutable defs reachable from any of "defs" must also be in + * the list; more formally, "defs" must be a transitive closure of mutable + * defs. + * + * After this operation succeeds, the finalized defs must only be accessed + * through a const pointer! */ static bool Freeze(Def* const* defs, int n, Status* status); static bool Freeze(const std::vector<Def*>& defs, Status* status); private: - UPB_DISALLOW_POD_OPS(Def, upb::Def); -, -UPB_DEFINE_STRUCT(upb_def, upb_refcounted, - const char *fullname; - upb_deftype_t type : 8; - // Used as a flag during the def's mutable stage. Must be false unless - // it is currently being used by a function on the stack. This allows - // us to easily determine which defs were passed into the function's - // current invocation. - bool came_from_user; -)); + UPB_DISALLOW_POD_OPS(Def, upb::Def) +}; -#define UPB_DEF_INIT(name, type, refs, ref2s) \ - { UPB_REFCOUNT_INIT(refs, ref2s), name, type, false } +#endif /* __cplusplus */ -UPB_BEGIN_EXTERN_C // { +UPB_BEGIN_EXTERN_C -// Native C API. +/* Native C API. */ upb_def *upb_def_dup(const upb_def *def, const void *owner); -// From upb_refcounted. -bool upb_def_isfrozen(const upb_def *def); -void upb_def_ref(const upb_def *def, const void *owner); -void upb_def_unref(const upb_def *def, const void *owner); -void upb_def_donateref(const upb_def *def, const void *from, const void *to); -void upb_def_checkref(const upb_def *def, const void *owner); +/* Include upb_refcounted methods like upb_def_ref()/upb_def_unref(). */ +UPB_REFCOUNTED_CMETHODS(upb_def, upb_def_upcast) upb_deftype_t upb_def_type(const upb_def *d); const char *upb_def_fullname(const upb_def *d); bool upb_def_setfullname(upb_def *def, const char *fullname, upb_status *s); bool upb_def_freeze(upb_def *const *defs, int n, upb_status *s); -UPB_END_EXTERN_C // } +UPB_END_EXTERN_C /* upb::Def casts *************************************************************/ @@ -1285,14 +1395,14 @@ UPB_END_EXTERN_C // } inline const cpptype *dyn_cast<const cpptype *, Def>(Def * def) { \ return upb_dyncast_##cname(def); \ } \ - } // namespace upb + } /* namespace upb */ #else #define UPB_CPP_CASTS(cname, cpptype) -#endif +#endif /* __cplusplus */ -// Dynamic casts, for determining if a def is of a particular type at runtime. -// Downcasts, for when some wants to assert that a def is of a particular type. -// These are only checked if we are building debug. +/* Dynamic casts, for determining if a def is of a particular type at runtime. + * Downcasts, for when some wants to assert that a def is of a particular type. + * These are only checked if we are building debug. */ #define UPB_DEF_CASTS(lower, upper, cpptype) \ UPB_INLINE const upb_##lower *upb_dyncast_##lower(const upb_def *def) { \ if (upb_def_type(def) != UPB_DEF_##upper) return NULL; \ @@ -1311,16 +1421,30 @@ UPB_END_EXTERN_C // } UPB_CPP_CASTS(lower, cpptype) #define UPB_DEFINE_DEF(cppname, lower, upper, cppmethods, members) \ - UPB_DEFINE_CLASS2(cppname, upb::Def, upb::RefCounted, UPB_QUOTE(cppmethods), \ + UPB_DEFINE_CLASS2(cppname, upb::Def, upb::RefCounted, cppmethods, \ members) \ UPB_DEF_CASTS(lower, upper, cppname) +#define UPB_DECLARE_DEF_TYPE(cppname, lower, upper) \ + UPB_DECLARE_DERIVED_TYPE2(cppname, upb::Def, upb::RefCounted, \ + upb_ ## lower, upb_def, upb_refcounted) \ + UPB_DEF_CASTS(lower, upper, cppname) + +UPB_DECLARE_DEF_TYPE(upb::FieldDef, fielddef, FIELD) +UPB_DECLARE_DEF_TYPE(upb::MessageDef, msgdef, MSG) +UPB_DECLARE_DEF_TYPE(upb::EnumDef, enumdef, ENUM) +UPB_DECLARE_DEF_TYPE(upb::OneofDef, oneofdef, ONEOF) + +#undef UPB_DECLARE_DEF_TYPE +#undef UPB_DEF_CASTS +#undef UPB_CPP_CASTS + /* upb::FieldDef **************************************************************/ -// The types a field can have. Note that this list is not identical to the -// types defined in descriptor.proto, which gives INT32 and SINT32 separate -// types (we distinguish the two with the "integer encoding" enum below). +/* The types a field can have. Note that this list is not identical to the + * types defined in descriptor.proto, which gives INT32 and SINT32 separate + * types (we distinguish the two with the "integer encoding" enum below). */ typedef enum { UPB_TYPE_FLOAT = 1, UPB_TYPE_DOUBLE = 2, @@ -1328,29 +1452,29 @@ typedef enum { UPB_TYPE_STRING = 4, UPB_TYPE_BYTES = 5, UPB_TYPE_MESSAGE = 6, - UPB_TYPE_ENUM = 7, // Enum values are int32. + UPB_TYPE_ENUM = 7, /* Enum values are int32. */ UPB_TYPE_INT32 = 8, UPB_TYPE_UINT32 = 9, UPB_TYPE_INT64 = 10, - UPB_TYPE_UINT64 = 11, + UPB_TYPE_UINT64 = 11 } upb_fieldtype_t; -// The repeated-ness of each field; this matches descriptor.proto. +/* The repeated-ness of each field; this matches descriptor.proto. */ typedef enum { UPB_LABEL_OPTIONAL = 1, UPB_LABEL_REQUIRED = 2, - UPB_LABEL_REPEATED = 3, + UPB_LABEL_REPEATED = 3 } upb_label_t; -// How integers should be encoded in serializations that offer multiple -// integer encoding methods. +/* How integers should be encoded in serializations that offer multiple + * integer encoding methods. */ typedef enum { UPB_INTFMT_VARIABLE = 1, UPB_INTFMT_FIXED = 2, - UPB_INTFMT_ZIGZAG = 3, // Only for signed types (INT32/INT64). + UPB_INTFMT_ZIGZAG = 3 /* Only for signed types (INT32/INT64). */ } upb_intfmt_t; -// Descriptor types, as defined in descriptor.proto. +/* Descriptor types, as defined in descriptor.proto. */ typedef enum { UPB_DESCRIPTOR_TYPE_DOUBLE = 1, UPB_DESCRIPTOR_TYPE_FLOAT = 2, @@ -1369,128 +1493,129 @@ typedef enum { UPB_DESCRIPTOR_TYPE_SFIXED32 = 15, UPB_DESCRIPTOR_TYPE_SFIXED64 = 16, UPB_DESCRIPTOR_TYPE_SINT32 = 17, - UPB_DESCRIPTOR_TYPE_SINT64 = 18, + UPB_DESCRIPTOR_TYPE_SINT64 = 18 } upb_descriptortype_t; +/* Maximum field number allowed for FieldDefs. This is an inherent limit of the + * protobuf wire format. */ +#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1) + +#ifdef __cplusplus -// A upb_fielddef describes a single field in a message. It is most often -// found as a part of a upb_msgdef, but can also stand alone to represent -// an extension. -// -// Its base class is upb::Def (use upb::upcast() to convert). -UPB_DEFINE_DEF(upb::FieldDef, fielddef, FIELD, +/* A upb_fielddef describes a single field in a message. It is most often + * found as a part of a upb_msgdef, but can also stand alone to represent + * an extension. + * + * Its base class is upb::Def (use upb::upcast() to convert). */ +class upb::FieldDef { public: typedef upb_fieldtype_t Type; typedef upb_label_t Label; typedef upb_intfmt_t IntegerFormat; typedef upb_descriptortype_t DescriptorType; - // These return true if the given value is a valid member of the enumeration. + /* These return true if the given value is a valid member of the enumeration. */ static bool CheckType(int32_t val); static bool CheckLabel(int32_t val); static bool CheckDescriptorType(int32_t val); static bool CheckIntegerFormat(int32_t val); - // These convert to the given enumeration; they require that the value is - // valid. + /* These convert to the given enumeration; they require that the value is + * valid. */ static Type ConvertType(int32_t val); static Label ConvertLabel(int32_t val); static DescriptorType ConvertDescriptorType(int32_t val); static IntegerFormat ConvertIntegerFormat(int32_t val); - // Returns NULL if memory allocation failed. + /* Returns NULL if memory allocation failed. */ static reffed_ptr<FieldDef> New(); - // Duplicates the given field, returning NULL if memory allocation failed. - // When a fielddef is duplicated, the subdef (if any) is made symbolic if it - // wasn't already. If the subdef is set but has no name (which is possible - // since msgdefs are not required to have a name) the new fielddef's subdef - // will be unset. + /* Duplicates the given field, returning NULL if memory allocation failed. + * When a fielddef is duplicated, the subdef (if any) is made symbolic if it + * wasn't already. If the subdef is set but has no name (which is possible + * since msgdefs are not required to have a name) the new fielddef's subdef + * will be unset. */ FieldDef* Dup(const void* owner) const; - // Functionality from upb::RefCounted. - bool IsFrozen() const; - void Ref(const void* owner) const; - void Unref(const void* owner) const; - void DonateRef(const void* from, const void* to) const; - void CheckRef(const void* owner) const; + /* upb::RefCounted methods like Ref()/Unref(). */ + UPB_REFCOUNTED_CPPMETHODS - // Functionality from upb::Def. + /* Functionality from upb::Def. */ const char* full_name() const; - bool type_is_set() const; // Whether set_[descriptor_]type() has been called. - Type type() const; // Requires that type_is_set() == true. - Label label() const; // Defaults to UPB_LABEL_OPTIONAL. - const char* name() const; // NULL if uninitialized. - uint32_t number() const; // Returns 0 if uninitialized. + bool type_is_set() const; /* set_[descriptor_]type() has been called? */ + Type type() const; /* Requires that type_is_set() == true. */ + Label label() const; /* Defaults to UPB_LABEL_OPTIONAL. */ + const char* name() const; /* NULL if uninitialized. */ + uint32_t number() const; /* Returns 0 if uninitialized. */ bool is_extension() const; - // For UPB_TYPE_MESSAGE fields only where is_tag_delimited() == false, - // indicates whether this field should have lazy parsing handlers that yield - // the unparsed string for the submessage. - // - // TODO(haberman): I think we want to move this into a FieldOptions container - // when we add support for custom options (the FieldOptions struct will - // contain both regular FieldOptions like "lazy" *and* custom options). + /* For UPB_TYPE_MESSAGE fields only where is_tag_delimited() == false, + * indicates whether this field should have lazy parsing handlers that yield + * the unparsed string for the submessage. + * + * TODO(haberman): I think we want to move this into a FieldOptions container + * when we add support for custom options (the FieldOptions struct will + * contain both regular FieldOptions like "lazy" *and* custom options). */ bool lazy() const; - // For non-string, non-submessage fields, this indicates whether binary - // protobufs are encoded in packed or non-packed format. - // - // TODO(haberman): see note above about putting options like this into a - // FieldOptions container. + /* For non-string, non-submessage fields, this indicates whether binary + * protobufs are encoded in packed or non-packed format. + * + * TODO(haberman): see note above about putting options like this into a + * FieldOptions container. */ bool packed() const; - // An integer that can be used as an index into an array of fields for - // whatever message this field belongs to. Guaranteed to be less than - // f->containing_type()->field_count(). May only be accessed once the def has - // been finalized. + /* An integer that can be used as an index into an array of fields for + * whatever message this field belongs to. Guaranteed to be less than + * f->containing_type()->field_count(). May only be accessed once the def has + * been finalized. */ int index() const; - // The MessageDef to which this field belongs. - // - // If this field has been added to a MessageDef, that message can be retrieved - // directly (this is always the case for frozen FieldDefs). - // - // If the field has not yet been added to a MessageDef, you can set the name - // of the containing type symbolically instead. This is mostly useful for - // extensions, where the extension is declared separately from the message. + /* The MessageDef to which this field belongs. + * + * If this field has been added to a MessageDef, that message can be retrieved + * directly (this is always the case for frozen FieldDefs). + * + * If the field has not yet been added to a MessageDef, you can set the name + * of the containing type symbolically instead. This is mostly useful for + * extensions, where the extension is declared separately from the message. */ const MessageDef* containing_type() const; const char* containing_type_name(); - // The OneofDef to which this field belongs, or NULL if this field is not part - // of a oneof. + /* The OneofDef to which this field belongs, or NULL if this field is not part + * of a oneof. */ const OneofDef* containing_oneof() const; - // The field's type according to the enum in descriptor.proto. This is not - // the same as UPB_TYPE_*, because it distinguishes between (for example) - // INT32 and SINT32, whereas our "type" enum does not. This return of - // descriptor_type() is a function of type(), integer_format(), and - // is_tag_delimited(). Likewise set_descriptor_type() sets all three - // appropriately. + /* The field's type according to the enum in descriptor.proto. This is not + * the same as UPB_TYPE_*, because it distinguishes between (for example) + * INT32 and SINT32, whereas our "type" enum does not. This return of + * descriptor_type() is a function of type(), integer_format(), and + * is_tag_delimited(). Likewise set_descriptor_type() sets all three + * appropriately. */ DescriptorType descriptor_type() const; - // Convenient field type tests. + /* Convenient field type tests. */ bool IsSubMessage() const; bool IsString() const; bool IsSequence() const; bool IsPrimitive() const; bool IsMap() const; - // How integers are encoded. Only meaningful for integer types. - // Defaults to UPB_INTFMT_VARIABLE, and is reset when "type" changes. + /* How integers are encoded. Only meaningful for integer types. + * Defaults to UPB_INTFMT_VARIABLE, and is reset when "type" changes. */ IntegerFormat integer_format() const; - // Whether a submessage field is tag-delimited or not (if false, then - // length-delimited). May only be set when type() == UPB_TYPE_MESSAGE. + /* Whether a submessage field is tag-delimited or not (if false, then + * length-delimited). May only be set when type() == UPB_TYPE_MESSAGE. */ bool is_tag_delimited() const; - // Returns the non-string default value for this fielddef, which may either - // be something the client set explicitly or the "default default" (0 for - // numbers, empty for strings). The field's type indicates the type of the - // returned value, except for enum fields that are still mutable. - // - // Requires that the given function matches the field's current type. + /* Returns the non-string default value for this fielddef, which may either + * be something the client set explicitly or the "default default" (0 for + * numbers, empty for strings). The field's type indicates the type of the + * returned value, except for enum fields that are still mutable. + * + * Requires that the given function matches the field's current type. */ int64_t default_int64() const; int32_t default_int32() const; uint64_t default_uint64() const; @@ -1499,83 +1624,81 @@ UPB_DEFINE_DEF(upb::FieldDef, fielddef, FIELD, float default_float() const; double default_double() const; - // The resulting string is always NULL-terminated. If non-NULL, the length - // will be stored in *len. + /* The resulting string is always NULL-terminated. If non-NULL, the length + * will be stored in *len. */ const char *default_string(size_t* len) const; - // For frozen UPB_TYPE_ENUM fields, enum defaults can always be read as either - // string or int32, and both of these methods will always return true. - // - // For mutable UPB_TYPE_ENUM fields, the story is a bit more complicated. - // Enum defaults are unusual. They can be specified either as string or int32, - // but to be valid the enum must have that value as a member. And if no - // default is specified, the "default default" comes from the EnumDef. - // - // We allow reading the default as either an int32 or a string, but only if - // we have a meaningful value to report. We have a meaningful value if it was - // set explicitly, or if we could get the "default default" from the EnumDef. - // Also if you explicitly set the name and we find the number in the EnumDef + /* For frozen UPB_TYPE_ENUM fields, enum defaults can always be read as either + * string or int32, and both of these methods will always return true. + * + * For mutable UPB_TYPE_ENUM fields, the story is a bit more complicated. + * Enum defaults are unusual. They can be specified either as string or int32, + * but to be valid the enum must have that value as a member. And if no + * default is specified, the "default default" comes from the EnumDef. + * + * We allow reading the default as either an int32 or a string, but only if + * we have a meaningful value to report. We have a meaningful value if it was + * set explicitly, or if we could get the "default default" from the EnumDef. + * Also if you explicitly set the name and we find the number in the EnumDef */ bool EnumHasStringDefault() const; bool EnumHasInt32Default() const; - // Submessage and enum fields must reference a "subdef", which is the - // upb::MessageDef or upb::EnumDef that defines their type. Note that when - // the FieldDef is mutable it may not have a subdef *yet*, but this function - // still returns true to indicate that the field's type requires a subdef. + /* Submessage and enum fields must reference a "subdef", which is the + * upb::MessageDef or upb::EnumDef that defines their type. Note that when + * the FieldDef is mutable it may not have a subdef *yet*, but this function + * still returns true to indicate that the field's type requires a subdef. */ bool HasSubDef() const; - // Returns the enum or submessage def for this field, if any. The field's - // type must match (ie. you may only call enum_subdef() for fields where - // type() == UPB_TYPE_ENUM). Returns NULL if the subdef has not been set or - // is currently set symbolically. + /* Returns the enum or submessage def for this field, if any. The field's + * type must match (ie. you may only call enum_subdef() for fields where + * type() == UPB_TYPE_ENUM). Returns NULL if the subdef has not been set or + * is currently set symbolically. */ const EnumDef* enum_subdef() const; const MessageDef* message_subdef() const; - // Returns the generic subdef for this field. Requires that HasSubDef() (ie. - // only works for UPB_TYPE_ENUM and UPB_TYPE_MESSAGE fields). + /* Returns the generic subdef for this field. Requires that HasSubDef() (ie. + * only works for UPB_TYPE_ENUM and UPB_TYPE_MESSAGE fields). */ const Def* subdef() const; - // Returns the symbolic name of the subdef. If the subdef is currently set - // unresolved (ie. set symbolically) returns the symbolic name. If it has - // been resolved to a specific subdef, returns the name from that subdef. + /* Returns the symbolic name of the subdef. If the subdef is currently set + * unresolved (ie. set symbolically) returns the symbolic name. If it has + * been resolved to a specific subdef, returns the name from that subdef. */ const char* subdef_name() const; - ////////////////////////////////////////////////////////////////////////////// - // Setters (non-const methods), only valid for mutable FieldDefs! - ////////////////////////////////////////////////////////////////////////////// + /* Setters (non-const methods), only valid for mutable FieldDefs! ***********/ bool set_full_name(const char* fullname, upb::Status* s); bool set_full_name(const std::string& fullname, upb::Status* s); - // This may only be called if containing_type() == NULL (ie. the field has not - // been added to a message yet). + /* This may only be called if containing_type() == NULL (ie. the field has not + * been added to a message yet). */ bool set_containing_type_name(const char *name, Status* status); bool set_containing_type_name(const std::string& name, Status* status); - // Defaults to false. When we freeze, we ensure that this can only be true - // for length-delimited message fields. Prior to freezing this can be true or - // false with no restrictions. + /* Defaults to false. When we freeze, we ensure that this can only be true + * for length-delimited message fields. Prior to freezing this can be true or + * false with no restrictions. */ void set_lazy(bool lazy); - // Defaults to true. Sets whether this field is encoded in packed format. + /* Defaults to true. Sets whether this field is encoded in packed format. */ void set_packed(bool packed); - // "type" or "descriptor_type" MUST be set explicitly before the fielddef is - // finalized. These setters require that the enum value is valid; if the - // value did not come directly from an enum constant, the caller should - // validate it first with the functions above (CheckFieldType(), etc). + /* "type" or "descriptor_type" MUST be set explicitly before the fielddef is + * finalized. These setters require that the enum value is valid; if the + * value did not come directly from an enum constant, the caller should + * validate it first with the functions above (CheckFieldType(), etc). */ void set_type(Type type); void set_label(Label label); void set_descriptor_type(DescriptorType type); void set_is_extension(bool is_extension); - // "number" and "name" must be set before the FieldDef is added to a - // MessageDef, and may not be set after that. - // - // "name" is the same as full_name()/set_full_name(), but since fielddefs - // most often use simple, non-qualified names, we provide this accessor - // also. Generally only extensions will want to think of this name as - // fully-qualified. + /* "number" and "name" must be set before the FieldDef is added to a + * MessageDef, and may not be set after that. + * + * "name" is the same as full_name()/set_full_name(), but since fielddefs + * most often use simple, non-qualified names, we provide this accessor + * also. Generally only extensions will want to think of this name as + * fully-qualified. */ bool set_number(uint32_t number, upb::Status* s); bool set_name(const char* name, upb::Status* s); bool set_name(const std::string& name, upb::Status* s); @@ -1583,12 +1706,12 @@ UPB_DEFINE_DEF(upb::FieldDef, fielddef, FIELD, void set_integer_format(IntegerFormat format); bool set_tag_delimited(bool tag_delimited, upb::Status* s); - // Sets default value for the field. The call must exactly match the type - // of the field. Enum fields may use either setint32 or setstring to set - // the default numerically or symbolically, respectively, but symbolic - // defaults must be resolved before finalizing (see ResolveEnumDefault()). - // - // Changing the type of a field will reset its default. + /* Sets default value for the field. The call must exactly match the type + * of the field. Enum fields may use either setint32 or setstring to set + * the default numerically or symbolically, respectively, but symbolic + * defaults must be resolved before finalizing (see ResolveEnumDefault()). + * + * Changing the type of a field will reset its default. */ void set_default_int64(int64_t val); void set_default_int32(int32_t val); void set_default_uint64(uint64_t val); @@ -1600,15 +1723,15 @@ UPB_DEFINE_DEF(upb::FieldDef, fielddef, FIELD, bool set_default_string(const std::string &str, Status *s); void set_default_cstr(const char *str, Status *s); - // Before a fielddef is frozen, its subdef may be set either directly (with a - // upb::Def*) or symbolically. Symbolic refs must be resolved before the - // containing msgdef can be frozen (see upb_resolve() above). upb always - // guarantees that any def reachable from a live def will also be kept alive. - // - // Both methods require that upb_hassubdef(f) (so the type must be set prior - // to calling these methods). Returns false if this is not the case, or if - // the given subdef is not of the correct type. The subdef is reset if the - // field's type is changed. The subdef can be set to NULL to clear it. + /* Before a fielddef is frozen, its subdef may be set either directly (with a + * upb::Def*) or symbolically. Symbolic refs must be resolved before the + * containing msgdef can be frozen (see upb_resolve() above). upb always + * guarantees that any def reachable from a live def will also be kept alive. + * + * Both methods require that upb_hassubdef(f) (so the type must be set prior + * to calling these methods). Returns false if this is not the case, or if + * the given subdef is not of the correct type. The subdef is reset if the + * field's type is changed. The subdef can be set to NULL to clear it. */ bool set_subdef(const Def* subdef, Status* s); bool set_enum_subdef(const EnumDef* subdef, Status* s); bool set_message_subdef(const MessageDef* subdef, Status* s); @@ -1616,66 +1739,21 @@ UPB_DEFINE_DEF(upb::FieldDef, fielddef, FIELD, bool set_subdef_name(const std::string &name, Status* s); private: - UPB_DISALLOW_POD_OPS(FieldDef, upb::FieldDef); -, -UPB_DEFINE_STRUCT(upb_fielddef, upb_def, - union { - int64_t sint; - uint64_t uint; - double dbl; - float flt; - void *bytes; - } defaultval; - union { - const upb_msgdef *def; // If !msg_is_symbolic. - char *name; // If msg_is_symbolic. - } msg; - union { - const upb_def *def; // If !subdef_is_symbolic. - char *name; // If subdef_is_symbolic. - } sub; // The msgdef or enumdef for this field, if upb_hassubdef(f). - bool subdef_is_symbolic; - bool msg_is_symbolic; - const upb_oneofdef *oneof; - bool default_is_string; - bool type_is_set_; // False until type is explicitly set. - bool is_extension_; - bool lazy_; - bool packed_; - upb_intfmt_t intfmt; - bool tagdelim; - upb_fieldtype_t type_; - upb_label_t label_; - uint32_t number_; - uint32_t selector_base; // Used to index into a upb::Handlers table. - uint32_t index_; -)); + UPB_DISALLOW_POD_OPS(FieldDef, upb::FieldDef) +}; -#define UPB_FIELDDEF_INIT(label, type, intfmt, tagdelim, is_extension, lazy, \ - packed, name, num, msgdef, subdef, selector_base, \ - index, defaultval, refs, ref2s) \ - { \ - UPB_DEF_INIT(name, UPB_DEF_FIELD, refs, ref2s), defaultval, {msgdef}, \ - {subdef}, NULL, false, false, \ - type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES, true, is_extension, \ - lazy, packed, intfmt, tagdelim, type, label, num, selector_base, index \ - } +# endif /* defined(__cplusplus) */ -UPB_BEGIN_EXTERN_C // { +UPB_BEGIN_EXTERN_C -// Native C API. +/* Native C API. */ upb_fielddef *upb_fielddef_new(const void *owner); upb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner); -// From upb_refcounted. -bool upb_fielddef_isfrozen(const upb_fielddef *f); -void upb_fielddef_ref(const upb_fielddef *f, const void *owner); -void upb_fielddef_unref(const upb_fielddef *f, const void *owner); -void upb_fielddef_donateref(const upb_fielddef *f, const void *from, - const void *to); -void upb_fielddef_checkref(const upb_fielddef *f, const void *owner); +/* Include upb_refcounted methods like upb_fielddef_ref(). */ +UPB_REFCOUNTED_CMETHODS(upb_fielddef, upb_fielddef_upcast2) -// From upb_def. +/* Methods from upb_def. */ const char *upb_fielddef_fullname(const upb_fielddef *f); bool upb_fielddef_setfullname(upb_fielddef *f, const char *fullname, upb_status *s); @@ -1754,7 +1832,7 @@ bool upb_fielddef_checktype(int32_t type); bool upb_fielddef_checkdescriptortype(int32_t type); bool upb_fielddef_checkintfmt(int32_t fmt); -UPB_END_EXTERN_C // } +UPB_END_EXTERN_C /* upb::MessageDef ************************************************************/ @@ -1762,66 +1840,64 @@ UPB_END_EXTERN_C // } typedef upb_inttable_iter upb_msg_field_iter; typedef upb_strtable_iter upb_msg_oneof_iter; -// Structure that describes a single .proto message type. -// -// Its base class is upb::Def (use upb::upcast() to convert). -UPB_DEFINE_DEF(upb::MessageDef, msgdef, MSG, UPB_QUOTE( +#ifdef __cplusplus + +/* Structure that describes a single .proto message type. + * + * Its base class is upb::Def (use upb::upcast() to convert). */ +class upb::MessageDef { public: - // Returns NULL if memory allocation failed. + /* Returns NULL if memory allocation failed. */ static reffed_ptr<MessageDef> New(); - // Functionality from upb::RefCounted. - bool IsFrozen() const; - void Ref(const void* owner) const; - void Unref(const void* owner) const; - void DonateRef(const void* from, const void* to) const; - void CheckRef(const void* owner) const; + /* upb::RefCounted methods like Ref()/Unref(). */ + UPB_REFCOUNTED_CPPMETHODS - // Functionality from upb::Def. + /* Functionality from upb::Def. */ const char* full_name() const; bool set_full_name(const char* fullname, Status* s); bool set_full_name(const std::string& fullname, Status* s); - // Call to freeze this MessageDef. - // WARNING: this will fail if this message has any unfrozen submessages! - // Messages with cycles must be frozen as a batch using upb::Def::Freeze(). + /* Call to freeze this MessageDef. + * WARNING: this will fail if this message has any unfrozen submessages! + * Messages with cycles must be frozen as a batch using upb::Def::Freeze(). */ bool Freeze(Status* s); - // The number of fields that belong to the MessageDef. + /* The number of fields that belong to the MessageDef. */ int field_count() const; - // The number of oneofs that belong to the MessageDef. + /* The number of oneofs that belong to the MessageDef. */ int oneof_count() const; - // Adds a field (upb_fielddef object) to a msgdef. Requires that the msgdef - // and the fielddefs are mutable. The fielddef's name and number must be - // set, and the message may not already contain any field with this name or - // number, and this fielddef may not be part of another message. In error - // cases false is returned and the msgdef is unchanged. - // - // If the given field is part of a oneof, this call succeeds if and only if - // that oneof is already part of this msgdef. (Note that adding a oneof to a - // msgdef automatically adds all of its fields to the msgdef at the time that - // the oneof is added, so it is usually more idiomatic to add the oneof's - // fields first then add the oneof to the msgdef. This case is supported for - // convenience.) - // - // If |f| is already part of this MessageDef, this method performs no action - // and returns true (success). Thus, this method is idempotent. + /* Adds a field (upb_fielddef object) to a msgdef. Requires that the msgdef + * and the fielddefs are mutable. The fielddef's name and number must be + * set, and the message may not already contain any field with this name or + * number, and this fielddef may not be part of another message. In error + * cases false is returned and the msgdef is unchanged. + * + * If the given field is part of a oneof, this call succeeds if and only if + * that oneof is already part of this msgdef. (Note that adding a oneof to a + * msgdef automatically adds all of its fields to the msgdef at the time that + * the oneof is added, so it is usually more idiomatic to add the oneof's + * fields first then add the oneof to the msgdef. This case is supported for + * convenience.) + * + * If |f| is already part of this MessageDef, this method performs no action + * and returns true (success). Thus, this method is idempotent. */ bool AddField(FieldDef* f, Status* s); bool AddField(const reffed_ptr<FieldDef>& f, Status* s); - // Adds a oneof (upb_oneofdef object) to a msgdef. Requires that the msgdef, - // oneof, and any fielddefs are mutable, that the fielddefs contained in the - // oneof do not have any name or number conflicts with existing fields in the - // msgdef, and that the oneof's name is unique among all oneofs in the msgdef. - // If the oneof is added successfully, all of its fields will be added - // directly to the msgdef as well. In error cases, false is returned and the - // msgdef is unchanged. + /* Adds a oneof (upb_oneofdef object) to a msgdef. Requires that the msgdef, + * oneof, and any fielddefs are mutable, that the fielddefs contained in the + * oneof do not have any name or number conflicts with existing fields in the + * msgdef, and that the oneof's name is unique among all oneofs in the msgdef. + * If the oneof is added successfully, all of its fields will be added + * directly to the msgdef as well. In error cases, false is returned and the + * msgdef is unchanged. */ bool AddOneof(OneofDef* o, Status* s); bool AddOneof(const reffed_ptr<OneofDef>& o, Status* s); - // These return NULL if the field is not found. + /* These return NULL if the field is not found. */ FieldDef* FindFieldByNumber(uint32_t number); FieldDef* FindFieldByName(const char *name, size_t len); const FieldDef* FindFieldByNumber(uint32_t number) const; @@ -1863,21 +1939,21 @@ UPB_DEFINE_DEF(upb::MessageDef, msgdef, MSG, UPB_QUOTE( return FindOneofByName(str.c_str(), str.size()); } - // Returns a new msgdef that is a copy of the given msgdef (and a copy of all - // the fields) but with any references to submessages broken and replaced - // with just the name of the submessage. Returns NULL if memory allocation - // failed. - // - // TODO(haberman): which is more useful, keeping fields resolved or - // unresolving them? If there's no obvious answer, Should this functionality - // just be moved into symtab.c? + /* Returns a new msgdef that is a copy of the given msgdef (and a copy of all + * the fields) but with any references to submessages broken and replaced + * with just the name of the submessage. Returns NULL if memory allocation + * failed. + * + * TODO(haberman): which is more useful, keeping fields resolved or + * unresolving them? If there's no obvious answer, Should this functionality + * just be moved into symtab.c? */ MessageDef* Dup(const void* owner) const; - // Is this message a map entry? + /* Is this message a map entry? */ void setmapentry(bool map_entry); bool mapentry() const; - // Iteration over fields. The order is undefined. + /* Iteration over fields. The order is undefined. */ class field_iterator : public std::iterator<std::forward_iterator_tag, FieldDef*> { public: @@ -1908,7 +1984,7 @@ UPB_DEFINE_DEF(upb::MessageDef, msgdef, MSG, UPB_QUOTE( upb_msg_field_iter iter_; }; - // Iteration over oneofs. The order is undefined. + /* Iteration over oneofs. The order is undefined. */ class oneof_iterator : public std::iterator<std::forward_iterator_tag, FieldDef*> { public: @@ -1991,52 +2067,21 @@ UPB_DEFINE_DEF(upb::MessageDef, msgdef, MSG, UPB_QUOTE( ConstOneofAccessor oneofs() const { return ConstOneofAccessor(this); } private: - UPB_DISALLOW_POD_OPS(MessageDef, upb::MessageDef); -), -UPB_DEFINE_STRUCT(upb_msgdef, upb_def, - size_t selector_count; - uint32_t submsg_field_count; - - // Tables for looking up fields by number and name. - upb_inttable itof; // int to field - upb_strtable ntof; // name to field - - // Tables for looking up oneofs by name. - upb_strtable ntoo; // name to oneof - - // Is this a map-entry message? - // TODO: set this flag properly for static descriptors; regenerate - // descriptor.upb.c. - bool map_entry; - - // TODO(haberman): proper extension ranges (there can be multiple). -)); + UPB_DISALLOW_POD_OPS(MessageDef, upb::MessageDef) +}; -// TODO: also support static initialization of the oneofs table. This will be -// needed if we compile in descriptors that contain oneofs. -#define UPB_MSGDEF_INIT(name, selector_count, submsg_field_count, itof, ntof, \ - refs, ref2s) \ - { \ - UPB_DEF_INIT(name, UPB_DEF_MSG, refs, ref2s), selector_count, \ - submsg_field_count, itof, ntof, \ - UPB_EMPTY_STRTABLE_INIT(UPB_CTYPE_PTR), false \ - } +#endif /* __cplusplus */ -UPB_BEGIN_EXTERN_C // { +UPB_BEGIN_EXTERN_C -// Returns NULL if memory allocation failed. +/* Returns NULL if memory allocation failed. */ upb_msgdef *upb_msgdef_new(const void *owner); -// From upb_refcounted. -bool upb_msgdef_isfrozen(const upb_msgdef *m); -void upb_msgdef_ref(const upb_msgdef *m, const void *owner); -void upb_msgdef_unref(const upb_msgdef *m, const void *owner); -void upb_msgdef_donateref(const upb_msgdef *m, const void *from, - const void *to); -void upb_msgdef_checkref(const upb_msgdef *m, const void *owner); +/* Include upb_refcounted methods like upb_msgdef_ref(). */ +UPB_REFCOUNTED_CMETHODS(upb_msgdef, upb_msgdef_upcast2) + bool upb_msgdef_freeze(upb_msgdef *m, upb_status *status); -// From upb_def. const char *upb_msgdef_fullname(const upb_msgdef *m); bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname, upb_status *s); @@ -2046,10 +2091,10 @@ bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor, bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor, upb_status *s); -// Field lookup in a couple of different variations: -// - itof = int to field -// - ntof = name to field -// - ntofz = name to field, null-terminated string. +/* Field lookup in a couple of different variations: + * - itof = int to field + * - ntof = name to field + * - ntofz = name to field, null-terminated string. */ const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i); const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name, size_t len); @@ -2069,9 +2114,9 @@ UPB_INLINE upb_fielddef *upb_msgdef_ntof_mutable(upb_msgdef *m, return (upb_fielddef *)upb_msgdef_ntof(m, name, len); } -// Oneof lookup: -// - ntoo = name to oneof -// - ntooz = name to oneof, null-terminated string. +/* Oneof lookup: + * - ntoo = name to oneof + * - ntooz = name to oneof, null-terminated string. */ const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name, size_t len); int upb_msgdef_numoneofs(const upb_msgdef *m); @@ -2089,7 +2134,7 @@ UPB_INLINE upb_oneofdef *upb_msgdef_ntoo_mutable(upb_msgdef *m, void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry); bool upb_msgdef_mapentry(const upb_msgdef *m); -// Well-known field tag numbers for map-entry messages. +/* Well-known field tag numbers for map-entry messages. */ #define UPB_MAPENTRY_KEY 1 #define UPB_MAPENTRY_VALUE 2 @@ -2097,95 +2142,94 @@ const upb_oneofdef *upb_msgdef_findoneof(const upb_msgdef *m, const char *name); int upb_msgdef_numoneofs(const upb_msgdef *m); -// upb_msg_field_iter i; -// for(upb_msg_field_begin(&i, m); -// !upb_msg_field_done(&i); -// upb_msg_field_next(&i)) { -// upb_fielddef *f = upb_msg_iter_field(&i); -// // ... -// } -// -// For C we don't have separate iterators for const and non-const. -// It is the caller's responsibility to cast the upb_fielddef* to -// const if the upb_msgdef* is const. +/* upb_msg_field_iter i; + * for(upb_msg_field_begin(&i, m); + * !upb_msg_field_done(&i); + * upb_msg_field_next(&i)) { + * upb_fielddef *f = upb_msg_iter_field(&i); + * // ... + * } + * + * For C we don't have separate iterators for const and non-const. + * It is the caller's responsibility to cast the upb_fielddef* to + * const if the upb_msgdef* is const. */ void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m); void upb_msg_field_next(upb_msg_field_iter *iter); bool upb_msg_field_done(const upb_msg_field_iter *iter); upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter); void upb_msg_field_iter_setdone(upb_msg_field_iter *iter); -// Similar to above, we also support iterating through the oneofs in a msgdef. +/* Similar to above, we also support iterating through the oneofs in a + * msgdef. */ void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m); void upb_msg_oneof_next(upb_msg_oneof_iter *iter); bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter); upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter); void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter); -UPB_END_EXTERN_C // } +UPB_END_EXTERN_C /* upb::EnumDef ***************************************************************/ typedef upb_strtable_iter upb_enum_iter; -// Class that represents an enum. Its base class is upb::Def (convert with -// upb::upcast()). -UPB_DEFINE_DEF(upb::EnumDef, enumdef, ENUM, +#ifdef __cplusplus + +/* Class that represents an enum. Its base class is upb::Def (convert with + * upb::upcast()). */ +class upb::EnumDef { public: - // Returns NULL if memory allocation failed. + /* Returns NULL if memory allocation failed. */ static reffed_ptr<EnumDef> New(); - // Functionality from upb::RefCounted. - bool IsFrozen() const; - void Ref(const void* owner) const; - void Unref(const void* owner) const; - void DonateRef(const void* from, const void* to) const; - void CheckRef(const void* owner) const; + /* upb::RefCounted methods like Ref()/Unref(). */ + UPB_REFCOUNTED_CPPMETHODS - // Functionality from upb::Def. + /* Functionality from upb::Def. */ const char* full_name() const; bool set_full_name(const char* fullname, Status* s); bool set_full_name(const std::string& fullname, Status* s); - // Call to freeze this EnumDef. + /* Call to freeze this EnumDef. */ bool Freeze(Status* s); - // The value that is used as the default when no field default is specified. - // If not set explicitly, the first value that was added will be used. - // The default value must be a member of the enum. - // Requires that value_count() > 0. + /* The value that is used as the default when no field default is specified. + * If not set explicitly, the first value that was added will be used. + * The default value must be a member of the enum. + * Requires that value_count() > 0. */ int32_t default_value() const; - // Sets the default value. If this value is not valid, returns false and an - // error message in status. + /* Sets the default value. If this value is not valid, returns false and an + * error message in status. */ bool set_default_value(int32_t val, Status* status); - // Returns the number of values currently defined in the enum. Note that - // multiple names can refer to the same number, so this may be greater than - // the total number of unique numbers. + /* Returns the number of values currently defined in the enum. Note that + * multiple names can refer to the same number, so this may be greater than + * the total number of unique numbers. */ int value_count() const; - // Adds a single name/number pair to the enum. Fails if this name has - // already been used by another value. + /* Adds a single name/number pair to the enum. Fails if this name has + * already been used by another value. */ bool AddValue(const char* name, int32_t num, Status* status); bool AddValue(const std::string& name, int32_t num, Status* status); - // Lookups from name to integer, returning true if found. + /* Lookups from name to integer, returning true if found. */ bool FindValueByName(const char* name, int32_t* num) const; - // Finds the name corresponding to the given number, or NULL if none was - // found. If more than one name corresponds to this number, returns the - // first one that was added. + /* Finds the name corresponding to the given number, or NULL if none was + * found. If more than one name corresponds to this number, returns the + * first one that was added. */ const char* FindValueByNumber(int32_t num) const; - // Returns a new EnumDef with all the same values. The new EnumDef will be - // owned by the given owner. + /* Returns a new EnumDef with all the same values. The new EnumDef will be + * owned by the given owner. */ EnumDef* Dup(const void* owner) const; - // Iteration over name/value pairs. The order is undefined. - // Adding an enum val invalidates any iterators. - // - // TODO: make compatible with range-for, with elements as pairs? + /* Iteration over name/value pairs. The order is undefined. + * Adding an enum val invalidates any iterators. + * + * TODO: make compatible with range-for, with elements as pairs? */ class Iterator { public: explicit Iterator(const EnumDef*); @@ -2200,33 +2244,23 @@ UPB_DEFINE_DEF(upb::EnumDef, enumdef, ENUM, }; private: - UPB_DISALLOW_POD_OPS(EnumDef, upb::EnumDef); -, -UPB_DEFINE_STRUCT(upb_enumdef, upb_def, - upb_strtable ntoi; - upb_inttable iton; - int32_t defaultval; -)); + UPB_DISALLOW_POD_OPS(EnumDef, upb::EnumDef) +}; -#define UPB_ENUMDEF_INIT(name, ntoi, iton, defaultval, refs, ref2s) \ - { UPB_DEF_INIT(name, UPB_DEF_ENUM, refs, ref2s), ntoi, iton, defaultval } +#endif /* __cplusplus */ -UPB_BEGIN_EXTERN_C // { +UPB_BEGIN_EXTERN_C -// Native C API. +/* Native C API. */ upb_enumdef *upb_enumdef_new(const void *owner); upb_enumdef *upb_enumdef_dup(const upb_enumdef *e, const void *owner); -// From upb_refcounted. -void upb_enumdef_unref(const upb_enumdef *e, const void *owner); -bool upb_enumdef_isfrozen(const upb_enumdef *e); -void upb_enumdef_ref(const upb_enumdef *e, const void *owner); -void upb_enumdef_donateref(const upb_enumdef *m, const void *from, - const void *to); -void upb_enumdef_checkref(const upb_enumdef *e, const void *owner); +/* Include upb_refcounted methods like upb_enumdef_ref(). */ +UPB_REFCOUNTED_CMETHODS(upb_enumdef, upb_enumdef_upcast2) + bool upb_enumdef_freeze(upb_enumdef *e, upb_status *status); -// From upb_def. +/* From upb_def. */ const char *upb_enumdef_fullname(const upb_enumdef *e); bool upb_enumdef_setfullname(upb_enumdef *e, const char *fullname, upb_status *s); @@ -2237,10 +2271,11 @@ int upb_enumdef_numvals(const upb_enumdef *e); bool upb_enumdef_addval(upb_enumdef *e, const char *name, int32_t num, upb_status *status); -// Enum lookups: -// - ntoi: look up a name with specified length. -// - ntoiz: look up a name provided as a null-terminated string. -// - iton: look up an integer, returning the name as a null-terminated string. +/* Enum lookups: + * - ntoi: look up a name with specified length. + * - ntoiz: look up a name provided as a null-terminated string. + * - iton: look up an integer, returning the name as a null-terminated + * string. */ bool upb_enumdef_ntoi(const upb_enumdef *e, const char *name, size_t len, int32_t *num); UPB_INLINE bool upb_enumdef_ntoiz(const upb_enumdef *e, @@ -2249,66 +2284,65 @@ UPB_INLINE bool upb_enumdef_ntoiz(const upb_enumdef *e, } const char *upb_enumdef_iton(const upb_enumdef *e, int32_t num); -// upb_enum_iter i; -// for(upb_enum_begin(&i, e); !upb_enum_done(&i); upb_enum_next(&i)) { -// // ... -// } +/* upb_enum_iter i; + * for(upb_enum_begin(&i, e); !upb_enum_done(&i); upb_enum_next(&i)) { + * // ... + * } + */ void upb_enum_begin(upb_enum_iter *iter, const upb_enumdef *e); void upb_enum_next(upb_enum_iter *iter); bool upb_enum_done(upb_enum_iter *iter); const char *upb_enum_iter_name(upb_enum_iter *iter); int32_t upb_enum_iter_number(upb_enum_iter *iter); -UPB_END_EXTERN_C // } +UPB_END_EXTERN_C /* upb::OneofDef **************************************************************/ typedef upb_inttable_iter upb_oneof_iter; -// Class that represents a oneof. Its base class is upb::Def (convert with -// upb::upcast()). -UPB_DEFINE_DEF(upb::OneofDef, oneofdef, ONEOF, UPB_QUOTE( +#ifdef __cplusplus + +/* Class that represents a oneof. Its base class is upb::Def (convert with + * upb::upcast()). */ +class upb::OneofDef { public: - // Returns NULL if memory allocation failed. + /* Returns NULL if memory allocation failed. */ static reffed_ptr<OneofDef> New(); - // Functionality from upb::RefCounted. - bool IsFrozen() const; - void Ref(const void* owner) const; - void Unref(const void* owner) const; - void DonateRef(const void* from, const void* to) const; - void CheckRef(const void* owner) const; + /* upb::RefCounted methods like Ref()/Unref(). */ + UPB_REFCOUNTED_CPPMETHODS - // Functionality from upb::Def. + /* Functionality from upb::Def. */ const char* full_name() const; - // Returns the MessageDef that owns this OneofDef. + /* Returns the MessageDef that owns this OneofDef. */ const MessageDef* containing_type() const; - // Returns the name of this oneof. This is the name used to look up the oneof - // by name once added to a message def. + /* Returns the name of this oneof. This is the name used to look up the oneof + * by name once added to a message def. */ const char* name() const; bool set_name(const char* name, Status* s); - // Returns the number of fields currently defined in the oneof. + /* Returns the number of fields currently defined in the oneof. */ int field_count() const; - // Adds a field to the oneof. The field must not have been added to any other - // oneof or msgdef. If the oneof is not yet part of a msgdef, then when the - // oneof is eventually added to a msgdef, all fields added to the oneof will - // also be added to the msgdef at that time. If the oneof is already part of a - // msgdef, the field must either be a part of that msgdef already, or must not - // be a part of any msgdef; in the latter case, the field is added to the - // msgdef as a part of this operation. - // - // The field may only have an OPTIONAL label, never REQUIRED or REPEATED. - // - // If |f| is already part of this MessageDef, this method performs no action - // and returns true (success). Thus, this method is idempotent. + /* Adds a field to the oneof. The field must not have been added to any other + * oneof or msgdef. If the oneof is not yet part of a msgdef, then when the + * oneof is eventually added to a msgdef, all fields added to the oneof will + * also be added to the msgdef at that time. If the oneof is already part of a + * msgdef, the field must either be a part of that msgdef already, or must not + * be a part of any msgdef; in the latter case, the field is added to the + * msgdef as a part of this operation. + * + * The field may only have an OPTIONAL label, never REQUIRED or REPEATED. + * + * If |f| is already part of this MessageDef, this method performs no action + * and returns true (success). Thus, this method is idempotent. */ bool AddField(FieldDef* field, Status* s); bool AddField(const reffed_ptr<FieldDef>& field, Status* s); - // Looks up by name. + /* Looks up by name. */ const FieldDef* FindFieldByName(const char* name, size_t len) const; FieldDef* FindFieldByName(const char* name, size_t len); const FieldDef* FindFieldByName(const char* name) const { @@ -2327,14 +2361,14 @@ UPB_DEFINE_DEF(upb::OneofDef, oneofdef, ONEOF, UPB_QUOTE( return FindFieldByName(str.c_str(), str.size()); } - // Looks up by tag number. + /* Looks up by tag number. */ const FieldDef* FindFieldByNumber(uint32_t num) const; - // Returns a new OneofDef with all the same fields. The OneofDef will be owned - // by the given owner. + /* Returns a new OneofDef with all the same fields. The OneofDef will be owned + * by the given owner. */ OneofDef* Dup(const void* owner) const; - // Iteration over fields. The order is undefined. + /* Iteration over fields. The order is undefined. */ class iterator : public std::iterator<std::forward_iterator_tag, FieldDef*> { public: explicit iterator(OneofDef* md); @@ -2370,30 +2404,19 @@ UPB_DEFINE_DEF(upb::OneofDef, oneofdef, ONEOF, UPB_QUOTE( const_iterator end() const; private: - UPB_DISALLOW_POD_OPS(OneofDef, upb::OneofDef); -), -UPB_DEFINE_STRUCT(upb_oneofdef, upb_def, - upb_strtable ntof; - upb_inttable itof; - const upb_msgdef *parent; -)); + UPB_DISALLOW_POD_OPS(OneofDef, upb::OneofDef) +}; -#define UPB_ONEOFDEF_INIT(name, ntof, itof, refs, ref2s) \ - { UPB_DEF_INIT(name, UPB_DEF_ENUM, refs, ref2s), ntof, itof } +#endif /* __cplusplus */ -UPB_BEGIN_EXTERN_C // { +UPB_BEGIN_EXTERN_C -// Native C API. +/* Native C API. */ upb_oneofdef *upb_oneofdef_new(const void *owner); upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner); -// From upb_refcounted. -void upb_oneofdef_unref(const upb_oneofdef *o, const void *owner); -bool upb_oneofdef_isfrozen(const upb_oneofdef *e); -void upb_oneofdef_ref(const upb_oneofdef *o, const void *owner); -void upb_oneofdef_donateref(const upb_oneofdef *m, const void *from, - const void *to); -void upb_oneofdef_checkref(const upb_oneofdef *o, const void *owner); +/* Include upb_refcounted methods like upb_oneofdef_ref(). */ +UPB_REFCOUNTED_CMETHODS(upb_oneofdef, upb_oneofdef_upcast2) const char *upb_oneofdef_name(const upb_oneofdef *o); bool upb_oneofdef_setname(upb_oneofdef *o, const char *name, upb_status *s); @@ -2404,10 +2427,10 @@ bool upb_oneofdef_addfield(upb_oneofdef *o, upb_fielddef *f, const void *ref_donor, upb_status *s); -// Oneof lookups: -// - ntof: look up a field by name. -// - ntofz: look up a field by name (as a null-terminated string). -// - itof: look up a field by number. +/* Oneof lookups: + * - ntof: look up a field by name. + * - ntofz: look up a field by name (as a null-terminated string). + * - itof: look up a field by number. */ const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o, const char *name, size_t length); UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o, @@ -2416,17 +2439,18 @@ UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o, } const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num); -// upb_oneof_iter i; -// for(upb_oneof_begin(&i, e); !upb_oneof_done(&i); upb_oneof_next(&i)) { -// // ... -// } +/* upb_oneof_iter i; + * for(upb_oneof_begin(&i, e); !upb_oneof_done(&i); upb_oneof_next(&i)) { + * // ... + * } + */ void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o); void upb_oneof_next(upb_oneof_iter *iter); bool upb_oneof_done(upb_oneof_iter *iter); upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter); void upb_oneof_iter_setdone(upb_oneof_iter *iter); -UPB_END_EXTERN_C // } +UPB_END_EXTERN_C #ifdef __cplusplus @@ -2435,21 +2459,12 @@ UPB_INLINE const char* upb_safecstr(const std::string& str) { return str.c_str(); } -// Inline C++ wrappers. +/* Inline C++ wrappers. */ namespace upb { inline Def* Def::Dup(const void* owner) const { return upb_def_dup(this, owner); } -inline bool Def::IsFrozen() const { return upb_def_isfrozen(this); } -inline void Def::Ref(const void* owner) const { upb_def_ref(this, owner); } -inline void Def::Unref(const void* owner) const { upb_def_unref(this, owner); } -inline void Def::DonateRef(const void* from, const void* to) const { - upb_def_donateref(this, from, to); -} -inline void Def::CheckRef(const void* owner) const { - upb_def_checkref(this, owner); -} inline Def::Type Def::def_type() const { return upb_def_type(this); } inline const char* Def::full_name() const { return upb_def_fullname(this); } inline bool Def::set_full_name(const char* fullname, Status* s) { @@ -2501,19 +2516,6 @@ inline reffed_ptr<FieldDef> FieldDef::New() { inline FieldDef* FieldDef::Dup(const void* owner) const { return upb_fielddef_dup(this, owner); } -inline bool FieldDef::IsFrozen() const { return upb_fielddef_isfrozen(this); } -inline void FieldDef::Ref(const void* owner) const { - upb_fielddef_ref(this, owner); -} -inline void FieldDef::Unref(const void* owner) const { - upb_fielddef_unref(this, owner); -} -inline void FieldDef::DonateRef(const void* from, const void* to) const { - upb_fielddef_donateref(this, from, to); -} -inline void FieldDef::CheckRef(const void* owner) const { - upb_fielddef_checkref(this, owner); -} inline const char* FieldDef::full_name() const { return upb_fielddef_fullname(this); } @@ -2679,19 +2681,6 @@ inline reffed_ptr<MessageDef> MessageDef::New() { upb_msgdef *m = upb_msgdef_new(&m); return reffed_ptr<MessageDef>(m, &m); } -inline bool MessageDef::IsFrozen() const { return upb_msgdef_isfrozen(this); } -inline void MessageDef::Ref(const void* owner) const { - return upb_msgdef_ref(this, owner); -} -inline void MessageDef::Unref(const void* owner) const { - return upb_msgdef_unref(this, owner); -} -inline void MessageDef::DonateRef(const void* from, const void* to) const { - return upb_msgdef_donateref(this, from, to); -} -inline void MessageDef::CheckRef(const void* owner) const { - return upb_msgdef_checkref(this, owner); -} inline const char *MessageDef::full_name() const { return upb_msgdef_fullname(this); } @@ -2879,19 +2868,6 @@ inline reffed_ptr<EnumDef> EnumDef::New() { upb_enumdef *e = upb_enumdef_new(&e); return reffed_ptr<EnumDef>(e, &e); } -inline bool EnumDef::IsFrozen() const { return upb_enumdef_isfrozen(this); } -inline void EnumDef::Ref(const void* owner) const { - return upb_enumdef_ref(this, owner); -} -inline void EnumDef::Unref(const void* owner) const { - return upb_enumdef_unref(this, owner); -} -inline void EnumDef::DonateRef(const void* from, const void* to) const { - return upb_enumdef_donateref(this, from, to); -} -inline void EnumDef::CheckRef(const void* owner) const { - return upb_enumdef_checkref(this, owner); -} inline const char* EnumDef::full_name() const { return upb_enumdef_fullname(this); } @@ -2944,19 +2920,6 @@ inline reffed_ptr<OneofDef> OneofDef::New() { upb_oneofdef *o = upb_oneofdef_new(&o); return reffed_ptr<OneofDef>(o, &o); } -inline bool OneofDef::IsFrozen() const { return upb_oneofdef_isfrozen(this); } -inline void OneofDef::Ref(const void* owner) const { - return upb_oneofdef_ref(this, owner); -} -inline void OneofDef::Unref(const void* owner) const { - return upb_oneofdef_unref(this, owner); -} -inline void OneofDef::DonateRef(const void* from, const void* to) const { - return upb_oneofdef_donateref(this, from, to); -} -inline void OneofDef::CheckRef(const void* owner) const { - return upb_oneofdef_checkref(this, owner); -} inline const char* OneofDef::full_name() const { return upb_oneofdef_name(this); } @@ -3038,1027 +3001,185 @@ inline bool OneofDef::const_iterator::operator!=( return !(*this == other); } -} // namespace upb +} /* namespace upb */ #endif -#undef UPB_DEFINE_DEF -#undef UPB_DEF_CASTS -#undef UPB_CPP_CASTS - #endif /* UPB_DEF_H_ */ -// This file contains accessors for a set of compiled-in defs. -// Note that unlike Google's protobuf, it does *not* define -// generated classes or any other kind of data structure for -// actually storing protobufs. It only contains *defs* which -// let you reflect over a protobuf *schema*. -// -// This file was generated by upbc (the upb compiler). -// Do not edit -- your changes will be discarded when the file is -// regenerated. - -#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_ -#define GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_ - /* * upb - a minimalist implementation of protocol buffers. * - * Copyright (c) 2009-2012 Google Inc. See LICENSE for details. + * Copyright (c) 2015 Google Inc. See LICENSE for details. * Author: Josh Haberman <jhaberman@gmail.com> * - * A symtab (symbol table) stores a name->def map of upb_defs. Clients could - * always create such tables themselves, but upb_symtab has logic for resolving - * symbolic references, and in particular, for keeping a whole set of consistent - * defs when replacing some subset of those defs. This logic is nontrivial. + * This file contains definitions of structs that should be considered private + * and NOT stable across versions of upb. * - * This is a mixed C/C++ interface that offers a full API to both languages. - * See the top-level README for more information. + * The only reason they are declared here and not in .c files is to allow upb + * and the application (if desired) to embed statically-initialized instances + * of structures like defs. + * + * If you include this file, all guarantees of ABI compatibility go out the + * window! Any code that includes this file needs to recompile against the + * exact same version of upb that they are linking against. + * + * You also need to recompile if you change the value of the UPB_DEBUG_REFS + * flag. */ -#ifndef UPB_SYMTAB_H_ -#define UPB_SYMTAB_H_ - - -#ifdef __cplusplus -#include <vector> -namespace upb { class SymbolTable; } -#endif - -UPB_DECLARE_TYPE(upb::SymbolTable, upb_symtab); - -typedef struct { - UPB_PRIVATE_FOR_CPP - upb_strtable_iter iter; - upb_deftype_t type; -} upb_symtab_iter; - -// Non-const methods in upb::SymbolTable are NOT thread-safe. -UPB_DEFINE_CLASS1(upb::SymbolTable, upb::RefCounted, - public: - // Returns a new symbol table with a single ref owned by "owner." - // Returns NULL if memory allocation failed. - static reffed_ptr<SymbolTable> New(); - - // Functionality from upb::RefCounted. - bool IsFrozen() const; - void Ref(const void* owner) const; - void Unref(const void* owner) const; - void DonateRef(const void *from, const void *to) const; - void CheckRef(const void *owner) const; - - // For all lookup functions, the returned pointer is not owned by the - // caller; it may be invalidated by any non-const call or unref of the - // SymbolTable! To protect against this, take a ref if desired. - - // Freezes the symbol table: prevents further modification of it. - // After the Freeze() operation is successful, the SymbolTable must only be - // accessed via a const pointer. - // - // Unlike with upb::MessageDef/upb::EnumDef/etc, freezing a SymbolTable is not - // a necessary step in using a SymbolTable. If you have no need for it to be - // immutable, there is no need to freeze it ever. However sometimes it is - // useful, and SymbolTables that are statically compiled into the binary are - // always frozen by nature. - void Freeze(); - - // Resolves the given symbol using the rules described in descriptor.proto, - // namely: - // - // 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). - // - // If not found, returns NULL. - const Def* Resolve(const char* base, const char* sym) const; - - // Finds an entry in the symbol table with this exact name. If not found, - // returns NULL. - const Def* Lookup(const char *sym) const; - const MessageDef* LookupMessage(const char *sym) const; - const EnumDef* LookupEnum(const char *sym) const; - - // TODO: introduce a C++ iterator, but make it nice and templated so that if - // you ask for an iterator of MessageDef the iterated elements are strongly - // typed as MessageDef*. - - // Adds the given mutable defs to the symtab, resolving all symbols - // (including enum default values) and finalizing the defs. Only one def per - // name may be in the list, but defs can replace existing defs in the symtab. - // All defs must have a name -- anonymous defs are not allowed. Anonymous - // defs can still be frozen by calling upb_def_freeze() directly. - // - // Any existing defs that can reach defs that are being replaced will - // themselves be replaced also, so that the resulting set of defs is fully - // consistent. - // - // This logic implemented in this method is a convenience; ultimately it - // calls some combination of upb_fielddef_setsubdef(), upb_def_dup(), and - // upb_freeze(), any of which the client could call themself. However, since - // the logic for doing so is nontrivial, we provide it here. - // - // The entire operation either succeeds or fails. If the operation fails, - // the symtab is unchanged, false is returned, and status indicates the - // error. The caller passes a ref on all defs to the symtab (even if the - // operation fails). - // - // TODO(haberman): currently failure will leave the symtab unchanged, but may - // leave the defs themselves partially resolved. Does this matter? If so we - // could do a prepass that ensures that all symbols are resolvable and bail - // if not, so we don't mutate anything until we know the operation will - // succeed. - // - // TODO(haberman): since the defs must be mutable, refining a frozen def - // requires making mutable copies of the entire tree. This is wasteful if - // only a few messages are changing. We may want to add a way of adding a - // tree of frozen defs to the symtab (perhaps an alternate constructor where - // you pass the root of the tree?) - bool Add(Def*const* defs, int n, void* ref_donor, upb_status* status); - - bool Add(const std::vector<Def*>& defs, void *owner, Status* status) { - return Add((Def*const*)&defs[0], defs.size(), owner, status); - } - - private: - UPB_DISALLOW_POD_OPS(SymbolTable, upb::SymbolTable); -, -UPB_DEFINE_STRUCT(upb_symtab, upb_refcounted, - upb_strtable symtab; -)); - -#define UPB_SYMTAB_INIT(symtab, refs, ref2s) \ - { UPB_REFCOUNT_INIT(refs, ref2s), symtab } - -UPB_BEGIN_EXTERN_C // { - -// Native C API. -// From upb_refcounted. -bool upb_symtab_isfrozen(const upb_symtab *s); -void upb_symtab_ref(const upb_symtab *s, const void *owner); -void upb_symtab_unref(const upb_symtab *s, const void *owner); -void upb_symtab_donateref( - const upb_symtab *s, const void *from, const void *to); -void upb_symtab_checkref(const upb_symtab *s, const void *owner); - -upb_symtab *upb_symtab_new(const void *owner); -void upb_symtab_freeze(upb_symtab *s); -const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base, - const char *sym); -const upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym); -const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym); -const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym); -bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor, - upb_status *status); - -// upb_symtab_iter i; -// for(upb_symtab_begin(&i, s, type); !upb_symtab_done(&i); -// upb_symtab_next(&i)) { -// const upb_def *def = upb_symtab_iter_def(&i); -// // ... -// } -// -// For C we don't have separate iterators for const and non-const. -// It is the caller's responsibility to cast the upb_fielddef* to -// const if the upb_msgdef* is const. -void upb_symtab_begin(upb_symtab_iter *iter, const upb_symtab *s, - upb_deftype_t type); -void upb_symtab_next(upb_symtab_iter *iter); -bool upb_symtab_done(const upb_symtab_iter *iter); -const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter); -UPB_END_EXTERN_C // } +#ifndef UPB_STATICINIT_H_ +#define UPB_STATICINIT_H_ #ifdef __cplusplus -// C++ inline wrappers. -namespace upb { -inline reffed_ptr<SymbolTable> SymbolTable::New() { - upb_symtab *s = upb_symtab_new(&s); - return reffed_ptr<SymbolTable>(s, &s); -} - -inline bool SymbolTable::IsFrozen() const { - return upb_symtab_isfrozen(this); -} -inline void SymbolTable::Ref(const void *owner) const { - upb_symtab_ref(this, owner); -} -inline void SymbolTable::Unref(const void *owner) const { - upb_symtab_unref(this, owner); -} -inline void SymbolTable::DonateRef(const void *from, const void *to) const { - upb_symtab_donateref(this, from, to); -} -inline void SymbolTable::CheckRef(const void *owner) const { - upb_symtab_checkref(this, owner); -} - -inline void SymbolTable::Freeze() { - return upb_symtab_freeze(this); -} -inline const Def *SymbolTable::Resolve(const char *base, - const char *sym) const { - return upb_symtab_resolve(this, base, sym); -} -inline const Def* SymbolTable::Lookup(const char *sym) const { - return upb_symtab_lookup(this, sym); -} -inline const MessageDef *SymbolTable::LookupMessage(const char *sym) const { - return upb_symtab_lookupmsg(this, sym); -} -inline bool SymbolTable::Add( - Def*const* defs, int n, void* ref_donor, upb_status* status) { - return upb_symtab_add(this, (upb_def*const*)defs, n, ref_donor, status); -} -} // namespace upb +/* Because of how we do our typedefs, this header can't be included from C++. */ +#error This file cannot be included from C++ #endif -#endif /* UPB_SYMTAB_H_ */ - -#ifdef __cplusplus -extern "C" { -#endif - -// Enums - -typedef enum { - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_OPTIONAL = 1, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REQUIRED = 2, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED = 3, -} google_protobuf_FieldDescriptorProto_Label; - -typedef enum { - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE = 1, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FLOAT = 2, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT64 = 3, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT64 = 4, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32 = 5, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED64 = 6, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED32 = 7, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BOOL = 8, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING = 9, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP = 10, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE = 11, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES = 12, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32 = 13, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ENUM = 14, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED32 = 15, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED64 = 16, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT32 = 17, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64 = 18, -} google_protobuf_FieldDescriptorProto_Type; - -typedef enum { - GOOGLE_PROTOBUF_FIELDOPTIONS_STRING = 0, - GOOGLE_PROTOBUF_FIELDOPTIONS_CORD = 1, - GOOGLE_PROTOBUF_FIELDOPTIONS_STRING_PIECE = 2, -} google_protobuf_FieldOptions_CType; - -typedef enum { - GOOGLE_PROTOBUF_FILEOPTIONS_SPEED = 1, - GOOGLE_PROTOBUF_FILEOPTIONS_CODE_SIZE = 2, - GOOGLE_PROTOBUF_FILEOPTIONS_LITE_RUNTIME = 3, -} google_protobuf_FileOptions_OptimizeMode; - -// Selectors - -// google.protobuf.DescriptorProto -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSUBMSG 3 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 4 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSUBMSG 5 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSUBMSG 6 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_STARTSUBMSG 7 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSEQ 8 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_ENDSEQ 9 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_ENDSUBMSG 10 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSEQ 11 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSEQ 12 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSUBMSG 13 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 14 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 15 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 16 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSEQ 17 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSEQ 18 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSUBMSG 19 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSEQ 20 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSEQ 21 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSUBMSG 22 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_ENDSUBMSG 23 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_STRING 24 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_STARTSTR 25 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_ENDSTR 26 - -// google.protobuf.DescriptorProto.ExtensionRange -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START_INT32 2 -#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END_INT32 3 - -// google.protobuf.EnumDescriptorProto -#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 3 -#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_STARTSEQ 4 -#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_ENDSEQ 5 -#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_ENDSUBMSG 6 -#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 7 -#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_STRING 8 -#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_STARTSTR 9 -#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_ENDSTR 10 - -// google.protobuf.EnumOptions -#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 -#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_ALLOW_ALIAS_BOOL 6 - -// google.protobuf.EnumValueDescriptorProto -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 3 -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_STRING 4 -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_STARTSTR 5 -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_ENDSTR 6 -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER_INT32 7 - -// google.protobuf.EnumValueOptions -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 - -// google.protobuf.FieldDescriptorProto -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 3 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_STRING 4 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_STARTSTR 5 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_ENDSTR 6 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STRING 7 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STARTSTR 8 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_ENDSTR 9 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER_INT32 10 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_INT32 11 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32 12 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STRING 13 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STARTSTR 14 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_ENDSTR 15 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STRING 16 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STARTSTR 17 -#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_ENDSTR 18 - -// google.protobuf.FieldOptions -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE_INT32 6 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED_BOOL 7 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED_BOOL 8 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_LAZY_BOOL 9 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_STRING 10 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_STARTSTR 11 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_ENDSTR 12 -#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_WEAK_BOOL 13 - -// google.protobuf.FileDescriptorProto -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 3 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSUBMSG 4 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSUBMSG 5 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 6 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_STARTSUBMSG 7 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_STARTSEQ 8 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_ENDSEQ 9 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_ENDSUBMSG 10 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 11 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 12 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 13 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSEQ 14 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSEQ 15 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSUBMSG 16 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSEQ 17 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSEQ 18 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSUBMSG 19 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 20 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_ENDSUBMSG 21 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_STRING 22 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_STARTSTR 23 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_ENDSTR 24 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_STRING 25 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_STARTSTR 26 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_ENDSTR 27 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSEQ 28 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSEQ 29 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STRING 30 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSTR 31 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSTR 32 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PUBLIC_DEPENDENCY_STARTSEQ 33 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PUBLIC_DEPENDENCY_ENDSEQ 34 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PUBLIC_DEPENDENCY_INT32 35 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_WEAK_DEPENDENCY_STARTSEQ 36 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_WEAK_DEPENDENCY_ENDSEQ 37 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_WEAK_DEPENDENCY_INT32 38 - -// google.protobuf.FileDescriptorSet -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSUBMSG 5 - -// google.protobuf.FileOptions -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STRING 6 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STARTSTR 7 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_ENDSTR 8 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STRING 9 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STARTSTR 10 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_ENDSTR 11 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR_INT32 12 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES_BOOL 13 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_GO_PACKAGE_STRING 14 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_GO_PACKAGE_STARTSTR 15 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_GO_PACKAGE_ENDSTR 16 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES_BOOL 17 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES_BOOL 18 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES_BOOL 19 -#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH_BOOL 20 - -// google.protobuf.MessageOptions -#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 -#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT_BOOL 6 -#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR_BOOL 7 - -// google.protobuf.MethodDescriptorProto -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 3 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_STRING 4 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_STARTSTR 5 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_ENDSTR 6 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STRING 7 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STARTSTR 8 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_ENDSTR 9 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_STRING 10 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_STARTSTR 11 -#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_ENDSTR 12 - -// google.protobuf.MethodOptions -#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 - -// google.protobuf.ServiceDescriptorProto -#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 3 -#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_STARTSEQ 4 -#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_ENDSEQ 5 -#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_ENDSUBMSG 6 -#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 7 -#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_STRING 8 -#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_STARTSTR 9 -#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_ENDSTR 10 - -// google.protobuf.ServiceOptions -#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 +/* upb_refcounted *************************************************************/ -// google.protobuf.SourceCodeInfo -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_ENDSUBMSG 5 -// google.protobuf.SourceCodeInfo.Location -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_STARTSEQ 2 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_ENDSEQ 3 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_INT32 4 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_STARTSEQ 5 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_ENDSEQ 6 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_INT32 7 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_COMMENTS_STRING 8 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_COMMENTS_STARTSTR 9 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_COMMENTS_ENDSTR 10 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_TRAILING_COMMENTS_STRING 11 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_TRAILING_COMMENTS_STARTSTR 12 -#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_TRAILING_COMMENTS_ENDSTR 13 +/* upb_def ********************************************************************/ -// google.protobuf.UninterpretedOption -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_STARTSUBMSG 2 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_STARTSEQ 3 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_ENDSEQ 4 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_ENDSUBMSG 5 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STRING 6 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STARTSTR 7 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_ENDSTR 8 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE_UINT64 9 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE_INT64 10 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE_DOUBLE 11 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STRING 12 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STARTSTR 13 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_ENDSTR 14 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STRING 15 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STARTSTR 16 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_ENDSTR 17 +struct upb_def { + upb_refcounted base; -// google.protobuf.UninterpretedOption.NamePart -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STRING 2 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STARTSTR 3 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_ENDSTR 4 -#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION_BOOL 5 + const char *fullname; + char type; /* A upb_deftype_t (char to save space) */ -const upb_symtab *upbdefs_google_protobuf_descriptor(const void *owner); + /* Used as a flag during the def's mutable stage. Must be false unless + * it is currently being used by a function on the stack. This allows + * us to easily determine which defs were passed into the function's + * current invocation. */ + bool came_from_user; +}; -// MessageDefs -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_DescriptorProto(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto.ExtensionRange"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumDescriptorProto(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumDescriptorProto"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumOptions(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumOptions"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumValueDescriptorProto(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumValueDescriptorProto"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumValueOptions(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumValueOptions"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FieldDescriptorProto(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FieldDescriptorProto"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FieldOptions(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FieldOptions"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FileDescriptorProto(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FileDescriptorProto"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FileDescriptorSet(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FileDescriptorSet"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FileOptions(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FileOptions"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_MessageOptions(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.MessageOptions"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_MethodDescriptorProto(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.MethodDescriptorProto"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_MethodOptions(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.MethodOptions"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_ServiceDescriptorProto(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.ServiceDescriptorProto"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_ServiceOptions(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.ServiceOptions"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.SourceCodeInfo"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_Location(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.SourceCodeInfo.Location"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.UninterpretedOption"); - assert(m); - return m; -} -UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_NamePart(const upb_symtab *s) { - const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.UninterpretedOption.NamePart"); - assert(m); - return m; -} +#define UPB_DEF_INIT(name, type, refs, ref2s) \ + { UPB_REFCOUNT_INIT(refs, ref2s), name, type, false } -// EnumDefs -UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Label(const upb_symtab *s) { - const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FieldDescriptorProto.Label"); - assert(e); - return e; -} -UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Type(const upb_symtab *s) { - const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FieldDescriptorProto.Type"); - assert(e); - return e; -} -UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FieldOptions_CType(const upb_symtab *s) { - const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FieldOptions.CType"); - assert(e); - return e; -} -UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FileOptions_OptimizeMode(const upb_symtab *s) { - const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FileOptions.OptimizeMode"); - assert(e); - return e; -} +/* upb_fielddef ***************************************************************/ -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_end(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto_ExtensionRange(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_start(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto_ExtensionRange(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_enum_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_extension(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_extension_range(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_field(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_nested_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 7); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumDescriptorProto(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumDescriptorProto(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumDescriptorProto(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_allow_alias(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumOptions(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumOptions(s), 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueDescriptorProto(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_number(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueDescriptorProto(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueDescriptorProto(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueOptions(s), 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_default_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 7); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_extendee(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_label(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_number(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 8); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_type_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_ctype(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_deprecated(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_experimental_map_key(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 9); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_lazy(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_packed(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_weak(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 10); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_dependency(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_enum_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_extension(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 7); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_message_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 8); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_package(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_public_dependency(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 10); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_service(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_source_code_info(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 9); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_weak_dependency(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 11); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorSet_file(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorSet(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_cc_generic_services(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 16); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_go_package(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 11); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_generate_equals_and_hash(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 20); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_generic_services(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 17); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_multiple_files(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 10); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_outer_classname(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 8); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_package(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_optimize_for(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 9); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_py_generic_services(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 18); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_message_set_wire_format(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_no_standard_descriptor_accessor(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_input_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_output_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodOptions(s), 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_method(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceDescriptorProto(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceDescriptorProto(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceDescriptorProto(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceOptions(s), 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_leading_comments(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_path(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_span(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_trailing_comments(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_location(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_is_extension(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption_NamePart(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_name_part(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption_NamePart(s), 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_aggregate_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 8); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_double_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_identifier_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_negative_int_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_positive_int_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_string_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 7); } +struct upb_fielddef { + upb_def base; -#ifdef __cplusplus -}; // extern "C" -#endif + union { + int64_t sint; + uint64_t uint; + double dbl; + float flt; + void *bytes; + } defaultval; + union { + const upb_msgdef *def; /* If !msg_is_symbolic. */ + char *name; /* If msg_is_symbolic. */ + } msg; + union { + const upb_def *def; /* If !subdef_is_symbolic. */ + char *name; /* If subdef_is_symbolic. */ + } sub; /* The msgdef or enumdef for this field, if upb_hassubdef(f). */ + bool subdef_is_symbolic; + bool msg_is_symbolic; + const upb_oneofdef *oneof; + bool default_is_string; + bool type_is_set_; /* False until type is explicitly set. */ + bool is_extension_; + bool lazy_; + bool packed_; + upb_intfmt_t intfmt; + bool tagdelim; + upb_fieldtype_t type_; + upb_label_t label_; + uint32_t number_; + uint32_t selector_base; /* Used to index into a upb::Handlers table. */ + uint32_t index_; +}; -#ifdef __cplusplus +#define UPB_FIELDDEF_INIT(label, type, intfmt, tagdelim, is_extension, lazy, \ + packed, name, num, msgdef, subdef, selector_base, \ + index, defaultval, refs, ref2s) \ + { \ + UPB_DEF_INIT(name, UPB_DEF_FIELD, refs, ref2s), defaultval, {msgdef}, \ + {subdef}, NULL, false, false, \ + type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES, true, is_extension, \ + lazy, packed, intfmt, tagdelim, type, label, num, selector_base, index \ + } -namespace upbdefs { -namespace google { -namespace protobuf { -namespace descriptor { -inline upb::reffed_ptr<const upb::SymbolTable> SymbolTable() { - const upb::SymbolTable* s = upbdefs_google_protobuf_descriptor(&s); - return upb::reffed_ptr<const upb::SymbolTable>(s, &s); -} -} // namespace descriptor -} // namespace protobuf -} // namespace google -#define RETURN_REFFED(type, func) \ - const type* obj = func(upbdefs::google::protobuf::descriptor::SymbolTable().get()); \ - return upb::reffed_ptr<const type>(obj); +/* upb_msgdef *****************************************************************/ -namespace google { -namespace protobuf { -namespace DescriptorProto { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_DescriptorProto) } -inline upb::reffed_ptr<const upb::FieldDef> enum_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_enum_type) } -inline upb::reffed_ptr<const upb::FieldDef> extension() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_extension) } -inline upb::reffed_ptr<const upb::FieldDef> extension_range() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_extension_range) } -inline upb::reffed_ptr<const upb::FieldDef> field() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_field) } -inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_name) } -inline upb::reffed_ptr<const upb::FieldDef> nested_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_nested_type) } -inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_options) } -} // namespace DescriptorProto -} // namespace protobuf -} // namespace google +struct upb_msgdef { + upb_def base; -namespace google { -namespace protobuf { -namespace DescriptorProto { -namespace ExtensionRange { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_DescriptorProto_ExtensionRange) } -inline upb::reffed_ptr<const upb::FieldDef> end() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_ExtensionRange_end) } -inline upb::reffed_ptr<const upb::FieldDef> start() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_ExtensionRange_start) } -} // namespace ExtensionRange -} // namespace DescriptorProto -} // namespace protobuf -} // namespace google + size_t selector_count; + uint32_t submsg_field_count; -namespace google { -namespace protobuf { -namespace EnumDescriptorProto { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumDescriptorProto) } -inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumDescriptorProto_name) } -inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumDescriptorProto_options) } -inline upb::reffed_ptr<const upb::FieldDef> value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumDescriptorProto_value) } -} // namespace EnumDescriptorProto -} // namespace protobuf -} // namespace google + /* Tables for looking up fields by number and name. */ + upb_inttable itof; /* int to field */ + upb_strtable ntof; /* name to field */ -namespace google { -namespace protobuf { -namespace EnumOptions { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumOptions) } -inline upb::reffed_ptr<const upb::FieldDef> allow_alias() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumOptions_allow_alias) } -inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumOptions_uninterpreted_option) } -} // namespace EnumOptions -} // namespace protobuf -} // namespace google + /* Tables for looking up oneofs by name. */ + upb_strtable ntoo; /* name to oneof */ -namespace google { -namespace protobuf { -namespace EnumValueDescriptorProto { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumValueDescriptorProto) } -inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueDescriptorProto_name) } -inline upb::reffed_ptr<const upb::FieldDef> number() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueDescriptorProto_number) } -inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueDescriptorProto_options) } -} // namespace EnumValueDescriptorProto -} // namespace protobuf -} // namespace google + /* Is this a map-entry message? + * TODO: set this flag properly for static descriptors; regenerate + * descriptor.upb.c. */ + bool map_entry; -namespace google { -namespace protobuf { -namespace EnumValueOptions { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumValueOptions) } -inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueOptions_uninterpreted_option) } -} // namespace EnumValueOptions -} // namespace protobuf -} // namespace google + /* TODO(haberman): proper extension ranges (there can be multiple). */ +}; -namespace google { -namespace protobuf { -namespace FieldDescriptorProto { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FieldDescriptorProto) } -inline upb::reffed_ptr<const upb::FieldDef> default_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_default_value) } -inline upb::reffed_ptr<const upb::FieldDef> extendee() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_extendee) } -inline upb::reffed_ptr<const upb::FieldDef> label() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_label) } -inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_name) } -inline upb::reffed_ptr<const upb::FieldDef> number() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_number) } -inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_options) } -inline upb::reffed_ptr<const upb::FieldDef> type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_type) } -inline upb::reffed_ptr<const upb::FieldDef> type_name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_type_name) } -inline upb::reffed_ptr<const upb::EnumDef> Label() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FieldDescriptorProto_Label) } -inline upb::reffed_ptr<const upb::EnumDef> Type() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FieldDescriptorProto_Type) } -} // namespace FieldDescriptorProto -} // namespace protobuf -} // namespace google +/* TODO: also support static initialization of the oneofs table. This will be + * needed if we compile in descriptors that contain oneofs. */ +#define UPB_MSGDEF_INIT(name, selector_count, submsg_field_count, itof, ntof, \ + refs, ref2s) \ + { \ + UPB_DEF_INIT(name, UPB_DEF_MSG, refs, ref2s), selector_count, \ + submsg_field_count, itof, ntof, \ + UPB_EMPTY_STRTABLE_INIT(UPB_CTYPE_PTR), false \ + } -namespace google { -namespace protobuf { -namespace FieldOptions { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FieldOptions) } -inline upb::reffed_ptr<const upb::FieldDef> ctype() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_ctype) } -inline upb::reffed_ptr<const upb::FieldDef> deprecated() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_deprecated) } -inline upb::reffed_ptr<const upb::FieldDef> experimental_map_key() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_experimental_map_key) } -inline upb::reffed_ptr<const upb::FieldDef> lazy() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_lazy) } -inline upb::reffed_ptr<const upb::FieldDef> packed() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_packed) } -inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_uninterpreted_option) } -inline upb::reffed_ptr<const upb::FieldDef> weak() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_weak) } -inline upb::reffed_ptr<const upb::EnumDef> CType() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FieldOptions_CType) } -} // namespace FieldOptions -} // namespace protobuf -} // namespace google -namespace google { -namespace protobuf { -namespace FileDescriptorProto { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FileDescriptorProto) } -inline upb::reffed_ptr<const upb::FieldDef> dependency() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_dependency) } -inline upb::reffed_ptr<const upb::FieldDef> enum_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_enum_type) } -inline upb::reffed_ptr<const upb::FieldDef> extension() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_extension) } -inline upb::reffed_ptr<const upb::FieldDef> message_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_message_type) } -inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_name) } -inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_options) } -inline upb::reffed_ptr<const upb::FieldDef> package() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_package) } -inline upb::reffed_ptr<const upb::FieldDef> public_dependency() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_public_dependency) } -inline upb::reffed_ptr<const upb::FieldDef> service() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_service) } -inline upb::reffed_ptr<const upb::FieldDef> source_code_info() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_source_code_info) } -inline upb::reffed_ptr<const upb::FieldDef> weak_dependency() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_weak_dependency) } -} // namespace FileDescriptorProto -} // namespace protobuf -} // namespace google +/* upb_enumdef ****************************************************************/ -namespace google { -namespace protobuf { -namespace FileDescriptorSet { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FileDescriptorSet) } -inline upb::reffed_ptr<const upb::FieldDef> file() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorSet_file) } -} // namespace FileDescriptorSet -} // namespace protobuf -} // namespace google +struct upb_enumdef { + upb_def base; -namespace google { -namespace protobuf { -namespace FileOptions { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FileOptions) } -inline upb::reffed_ptr<const upb::FieldDef> cc_generic_services() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_cc_generic_services) } -inline upb::reffed_ptr<const upb::FieldDef> go_package() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_go_package) } -inline upb::reffed_ptr<const upb::FieldDef> java_generate_equals_and_hash() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_generate_equals_and_hash) } -inline upb::reffed_ptr<const upb::FieldDef> java_generic_services() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_generic_services) } -inline upb::reffed_ptr<const upb::FieldDef> java_multiple_files() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_multiple_files) } -inline upb::reffed_ptr<const upb::FieldDef> java_outer_classname() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_outer_classname) } -inline upb::reffed_ptr<const upb::FieldDef> java_package() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_package) } -inline upb::reffed_ptr<const upb::FieldDef> optimize_for() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_optimize_for) } -inline upb::reffed_ptr<const upb::FieldDef> py_generic_services() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_py_generic_services) } -inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_uninterpreted_option) } -inline upb::reffed_ptr<const upb::EnumDef> OptimizeMode() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FileOptions_OptimizeMode) } -} // namespace FileOptions -} // namespace protobuf -} // namespace google + upb_strtable ntoi; + upb_inttable iton; + int32_t defaultval; +}; -namespace google { -namespace protobuf { -namespace MessageOptions { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_MessageOptions) } -inline upb::reffed_ptr<const upb::FieldDef> message_set_wire_format() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_message_set_wire_format) } -inline upb::reffed_ptr<const upb::FieldDef> no_standard_descriptor_accessor() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_no_standard_descriptor_accessor) } -inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_uninterpreted_option) } -} // namespace MessageOptions -} // namespace protobuf -} // namespace google +#define UPB_ENUMDEF_INIT(name, ntoi, iton, defaultval, refs, ref2s) \ + { UPB_DEF_INIT(name, UPB_DEF_ENUM, refs, ref2s), ntoi, iton, defaultval } -namespace google { -namespace protobuf { -namespace MethodDescriptorProto { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_MethodDescriptorProto) } -inline upb::reffed_ptr<const upb::FieldDef> input_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_input_type) } -inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_name) } -inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_options) } -inline upb::reffed_ptr<const upb::FieldDef> output_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_output_type) } -} // namespace MethodDescriptorProto -} // namespace protobuf -} // namespace google -namespace google { -namespace protobuf { -namespace MethodOptions { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_MethodOptions) } -inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodOptions_uninterpreted_option) } -} // namespace MethodOptions -} // namespace protobuf -} // namespace google +/* upb_oneofdef ***************************************************************/ -namespace google { -namespace protobuf { -namespace ServiceDescriptorProto { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_ServiceDescriptorProto) } -inline upb::reffed_ptr<const upb::FieldDef> method() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceDescriptorProto_method) } -inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceDescriptorProto_name) } -inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceDescriptorProto_options) } -} // namespace ServiceDescriptorProto -} // namespace protobuf -} // namespace google +struct upb_oneofdef { + upb_def base; -namespace google { -namespace protobuf { -namespace ServiceOptions { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_ServiceOptions) } -inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceOptions_uninterpreted_option) } -} // namespace ServiceOptions -} // namespace protobuf -} // namespace google + upb_strtable ntof; + upb_inttable itof; + const upb_msgdef *parent; +}; -namespace google { -namespace protobuf { -namespace SourceCodeInfo { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_SourceCodeInfo) } -inline upb::reffed_ptr<const upb::FieldDef> location() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_location) } -} // namespace SourceCodeInfo -} // namespace protobuf -} // namespace google +#define UPB_ONEOFDEF_INIT(name, ntof, itof, refs, ref2s) \ + { UPB_DEF_INIT(name, UPB_DEF_ENUM, refs, ref2s), ntof, itof } -namespace google { -namespace protobuf { -namespace SourceCodeInfo { -namespace Location { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_SourceCodeInfo_Location) } -inline upb::reffed_ptr<const upb::FieldDef> leading_comments() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_leading_comments) } -inline upb::reffed_ptr<const upb::FieldDef> path() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_path) } -inline upb::reffed_ptr<const upb::FieldDef> span() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_span) } -inline upb::reffed_ptr<const upb::FieldDef> trailing_comments() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_trailing_comments) } -} // namespace Location -} // namespace SourceCodeInfo -} // namespace protobuf -} // namespace google -namespace google { -namespace protobuf { -namespace UninterpretedOption { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_UninterpretedOption) } -inline upb::reffed_ptr<const upb::FieldDef> aggregate_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_aggregate_value) } -inline upb::reffed_ptr<const upb::FieldDef> double_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_double_value) } -inline upb::reffed_ptr<const upb::FieldDef> identifier_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_identifier_value) } -inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_name) } -inline upb::reffed_ptr<const upb::FieldDef> negative_int_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_negative_int_value) } -inline upb::reffed_ptr<const upb::FieldDef> positive_int_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_positive_int_value) } -inline upb::reffed_ptr<const upb::FieldDef> string_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_string_value) } -} // namespace UninterpretedOption -} // namespace protobuf -} // namespace google +/* upb_symtab *****************************************************************/ -namespace google { -namespace protobuf { -namespace UninterpretedOption { -namespace NamePart { -inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_UninterpretedOption_NamePart) } -inline upb::reffed_ptr<const upb::FieldDef> is_extension() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_NamePart_is_extension) } -inline upb::reffed_ptr<const upb::FieldDef> name_part() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_NamePart_name_part) } -} // namespace NamePart -} // namespace UninterpretedOption -} // namespace protobuf -} // namespace google +struct upb_symtab { + upb_refcounted base; -} // namespace upbdefs + upb_strtable symtab; +}; +#define UPB_SYMTAB_INIT(symtab, refs, ref2s) \ + { UPB_REFCOUNT_INIT(refs, ref2s), symtab } -#undef RETURN_REFFED -#endif // __cplusplus -#endif // GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_ +#endif /* UPB_STATICINIT_H_ */ /* * upb - a minimalist implementation of protocol buffers. * @@ -4092,25 +3213,26 @@ class HandlerAttributes; class Handlers; template <class T> class Handler; template <class T> struct CanonicalType; -} // namespace upb +} /* namespace upb */ #endif -UPB_DECLARE_TYPE(upb::BufferHandle, upb_bufhandle); -UPB_DECLARE_TYPE(upb::BytesHandler, upb_byteshandler); -UPB_DECLARE_TYPE(upb::HandlerAttributes, upb_handlerattr); -UPB_DECLARE_TYPE(upb::Handlers, upb_handlers); - -// The maximum depth that the handler graph can have. This is a resource limit -// for the C stack since we sometimes need to recursively traverse the graph. -// Cycles are ok; the traversal will stop when it detects a cycle, but we must -// hit the cycle before the maximum depth is reached. -// -// If having a single static limit is too inflexible, we can add another variant -// of Handlers::Freeze that allows specifying this as a parameter. +UPB_DECLARE_TYPE(upb::BufferHandle, upb_bufhandle) +UPB_DECLARE_TYPE(upb::BytesHandler, upb_byteshandler) +UPB_DECLARE_TYPE(upb::HandlerAttributes, upb_handlerattr) +UPB_DECLARE_DERIVED_TYPE(upb::Handlers, upb::RefCounted, + upb_handlers, upb_refcounted) + +/* The maximum depth that the handler graph can have. This is a resource limit + * for the C stack since we sometimes need to recursively traverse the graph. + * Cycles are ok; the traversal will stop when it detects a cycle, but we must + * hit the cycle before the maximum depth is reached. + * + * If having a single static limit is too inflexible, we can add another variant + * of Handlers::Freeze that allows specifying this as a parameter. */ #define UPB_MAX_HANDLER_DEPTH 64 -// All the different types of handlers that can be registered. -// Only needed for the advanced functions in upb::Handlers. +/* All the different types of handlers that can be registered. + * Only needed for the advanced functions in upb::Handlers. */ typedef enum { UPB_HANDLER_INT32, UPB_HANDLER_INT64, @@ -4125,25 +3247,25 @@ typedef enum { UPB_HANDLER_STARTSUBMSG, UPB_HANDLER_ENDSUBMSG, UPB_HANDLER_STARTSEQ, - UPB_HANDLER_ENDSEQ, + UPB_HANDLER_ENDSEQ } upb_handlertype_t; #define UPB_HANDLER_MAX (UPB_HANDLER_ENDSEQ+1) #define UPB_BREAK NULL -// A convenient definition for when no closure is needed. +/* A convenient definition for when no closure is needed. */ extern char _upb_noclosure; #define UPB_NO_CLOSURE &_upb_noclosure -// A selector refers to a specific field handler in the Handlers object -// (for example: the STARTSUBMSG handler for field "field15"). +/* A selector refers to a specific field handler in the Handlers object + * (for example: the STARTSUBMSG handler for field "field15"). */ typedef int32_t upb_selector_t; UPB_BEGIN_EXTERN_C -// Forward-declares for C inline accessors. We need to declare these here -// so we can "friend" them in the class declarations in C++. +/* Forward-declares for C inline accessors. We need to declare these here + * so we can "friend" them in the class declarations in C++. */ UPB_INLINE upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s); UPB_INLINE const void *upb_handlerattr_handlerdata(const upb_handlerattr *attr); @@ -4162,104 +3284,111 @@ UPB_INLINE const char *upb_bufhandle_buf(const upb_bufhandle *h); UPB_END_EXTERN_C -// Static selectors for upb::Handlers. +/* Static selectors for upb::Handlers. */ #define UPB_STARTMSG_SELECTOR 0 #define UPB_ENDMSG_SELECTOR 1 #define UPB_STATIC_SELECTOR_COUNT 2 -// Static selectors for upb::BytesHandler. +/* Static selectors for upb::BytesHandler. */ #define UPB_STARTSTR_SELECTOR 0 #define UPB_STRING_SELECTOR 1 #define UPB_ENDSTR_SELECTOR 2 typedef void upb_handlerfree(void *d); -// A set of attributes that accompanies a handler's function pointer. -UPB_DEFINE_CLASS0(upb::HandlerAttributes, +#ifdef __cplusplus + +/* A set of attributes that accompanies a handler's function pointer. */ +class upb::HandlerAttributes { public: HandlerAttributes(); ~HandlerAttributes(); - // Sets the handler data that will be passed as the second parameter of the - // handler. To free this pointer when the handlers are freed, call - // Handlers::AddCleanup(). + /* Sets the handler data that will be passed as the second parameter of the + * handler. To free this pointer when the handlers are freed, call + * Handlers::AddCleanup(). */ bool SetHandlerData(const void *handler_data); const void* handler_data() const; - // Use this to specify the type of the closure. This will be checked against - // all other closure types for handler that use the same closure. - // Registration will fail if this does not match all other non-NULL closure - // types. + /* Use this to specify the type of the closure. This will be checked against + * all other closure types for handler that use the same closure. + * Registration will fail if this does not match all other non-NULL closure + * types. */ bool SetClosureType(const void *closure_type); const void* closure_type() const; - // Use this to specify the type of the returned closure. Only used for - // Start*{String,SubMessage,Sequence} handlers. This must match the closure - // type of any handlers that use it (for example, the StringBuf handler must - // match the closure returned from StartString). + /* Use this to specify the type of the returned closure. Only used for + * Start*{String,SubMessage,Sequence} handlers. This must match the closure + * type of any handlers that use it (for example, the StringBuf handler must + * match the closure returned from StartString). */ bool SetReturnClosureType(const void *return_closure_type); const void* return_closure_type() const; - // Set to indicate that the handler always returns "ok" (either "true" or a - // non-NULL closure). This is a hint that can allow code generators to - // generate more efficient code. + /* Set to indicate that the handler always returns "ok" (either "true" or a + * non-NULL closure). This is a hint that can allow code generators to + * generate more efficient code. */ bool SetAlwaysOk(bool always_ok); bool always_ok() const; private: friend UPB_INLINE const void * ::upb_handlerattr_handlerdata( const upb_handlerattr *attr); -, -UPB_DEFINE_STRUCT0(upb_handlerattr, +#else +struct upb_handlerattr { +#endif const void *handler_data_; const void *closure_type_; const void *return_closure_type_; bool alwaysok_; -)); +}; #define UPB_HANDLERATTR_INITIALIZER {NULL, NULL, NULL, false} typedef struct { upb_func *func; - // It is wasteful to include the entire attributes here: - // - // * Some of the information is redundant (like storing the closure type - // separately for each handler that must match). - // * Some of the info is only needed prior to freeze() (like closure types). - // * alignment padding wastes a lot of space for alwaysok_. - // - // If/when the size and locality of handlers is an issue, we can optimize this - // not to store the entire attr like this. We do not expose the table's - // layout to allow this optimization in the future. + + /* It is wasteful to include the entire attributes here: + * + * * Some of the information is redundant (like storing the closure type + * separately for each handler that must match). + * * Some of the info is only needed prior to freeze() (like closure types). + * * alignment padding wastes a lot of space for alwaysok_. + * + * If/when the size and locality of handlers is an issue, we can optimize this + * not to store the entire attr like this. We do not expose the table's + * layout to allow this optimization in the future. */ upb_handlerattr attr; } upb_handlers_tabent; -// Extra information about a buffer that is passed to a StringBuf handler. -// TODO(haberman): allow the handle to be pinned so that it will outlive -// the handler invocation. -UPB_DEFINE_CLASS0(upb::BufferHandle, +#ifdef __cplusplus + +/* Extra information about a buffer that is passed to a StringBuf handler. + * TODO(haberman): allow the handle to be pinned so that it will outlive + * the handler invocation. */ +class upb::BufferHandle { public: BufferHandle(); ~BufferHandle(); - // The beginning of the buffer. This may be different than the pointer - // passed to a StringBuf handler because the handler may receive data - // that is from the middle or end of a larger buffer. + /* The beginning of the buffer. This may be different than the pointer + * passed to a StringBuf handler because the handler may receive data + * that is from the middle or end of a larger buffer. */ const char* buffer() const; - // The offset within the attached object where this buffer begins. Only - // meaningful if there is an attached object. + /* The offset within the attached object where this buffer begins. Only + * meaningful if there is an attached object. */ size_t object_offset() const; - // Note that object_offset is the offset of "buf" within the attached object. + /* Note that object_offset is the offset of "buf" within the attached + * object. */ void SetBuffer(const char* buf, size_t object_offset); - // The BufferHandle can have an "attached object", which can be used to - // tunnel through a pointer to the buffer's underlying representation. + /* The BufferHandle can have an "attached object", which can be used to + * tunnel through a pointer to the buffer's underlying representation. */ template <class T> void SetAttachedObject(const T* obj); - // Returns NULL if the attached object is not of this type. + /* Returns NULL if the attached object is not of this type. */ template <class T> const T* GetAttachedObject() const; @@ -4274,26 +3403,29 @@ UPB_DEFINE_CLASS0(upb::BufferHandle, friend UPB_INLINE const void* ::upb_bufhandle_objtype( const upb_bufhandle *h); friend UPB_INLINE const char* ::upb_bufhandle_buf(const upb_bufhandle *h); -, -UPB_DEFINE_STRUCT0(upb_bufhandle, +#else +struct upb_bufhandle { +#endif const char *buf_; const void *obj_; const void *objtype_; size_t objofs_; -)); - -// A upb::Handlers object represents the set of handlers associated with a -// message in the graph of messages. You can think of it as a big virtual -// table with functions corresponding to all the events that can fire while -// parsing or visiting a message of a specific type. -// -// Any handlers that are not set behave as if they had successfully consumed -// the value. Any unset Start* handlers will propagate their closure to the -// inner frame. -// -// The easiest way to create the *Handler objects needed by the Set* methods is -// with the UpbBind() and UpbMakeHandler() macros; see below. -UPB_DEFINE_CLASS1(upb::Handlers, upb::RefCounted, +}; + +#ifdef __cplusplus + +/* A upb::Handlers object represents the set of handlers associated with a + * message in the graph of messages. You can think of it as a big virtual + * table with functions corresponding to all the events that can fire while + * parsing or visiting a message of a specific type. + * + * Any handlers that are not set behave as if they had successfully consumed + * the value. Any unset Start* handlers will propagate their closure to the + * inner frame. + * + * The easiest way to create the *Handler objects needed by the Set* methods is + * with the UpbBind() and UpbMakeHandler() macros; see below. */ +class upb::Handlers { public: typedef upb_selector_t Selector; typedef upb_handlertype_t Type; @@ -4318,95 +3450,94 @@ UPB_DEFINE_CLASS1(upb::Handlers, upb::RefCounted, typedef ValueHandler<double>::H DoubleHandler; typedef ValueHandler<bool>::H BoolHandler; - // Any function pointer can be converted to this and converted back to its - // correct type. + /* Any function pointer can be converted to this and converted back to its + * correct type. */ typedef void GenericFunction(); typedef void HandlersCallback(const void *closure, upb_handlers *h); - // Returns a new handlers object for the given frozen msgdef. - // Returns NULL if memory allocation failed. + /* Returns a new handlers object for the given frozen msgdef. + * Returns NULL if memory allocation failed. */ static reffed_ptr<Handlers> New(const MessageDef *m); - // Convenience function for registering a graph of handlers that mirrors the - // graph of msgdefs for some message. For "m" and all its children a new set - // of handlers will be created and the given callback will be invoked, - // allowing the client to register handlers for this message. Note that any - // subhandlers set by the callback will be overwritten. + /* Convenience function for registering a graph of handlers that mirrors the + * graph of msgdefs for some message. For "m" and all its children a new set + * of handlers will be created and the given callback will be invoked, + * allowing the client to register handlers for this message. Note that any + * subhandlers set by the callback will be overwritten. */ static reffed_ptr<const Handlers> NewFrozen(const MessageDef *m, HandlersCallback *callback, const void *closure); - // Functionality from upb::RefCounted. - bool IsFrozen() const; - void Ref(const void* owner) const; - void Unref(const void* owner) const; - void DonateRef(const void *from, const void *to) const; - void CheckRef(const void *owner) const; + /* Functionality from upb::RefCounted. */ + UPB_REFCOUNTED_CPPMETHODS - // All handler registration functions return bool to indicate success or - // failure; details about failures are stored in this status object. If a - // failure does occur, it must be cleared before the Handlers are frozen, - // otherwise the freeze() operation will fail. The functions may *only* be - // used while the Handlers are mutable. + /* All handler registration functions return bool to indicate success or + * failure; details about failures are stored in this status object. If a + * failure does occur, it must be cleared before the Handlers are frozen, + * otherwise the freeze() operation will fail. The functions may *only* be + * used while the Handlers are mutable. */ const Status* status(); void ClearError(); - // Call to freeze these Handlers. Requires that any SubHandlers are already - // frozen. For cycles, you must use the static version below and freeze the - // whole graph at once. + /* Call to freeze these Handlers. Requires that any SubHandlers are already + * frozen. For cycles, you must use the static version below and freeze the + * whole graph at once. */ bool Freeze(Status* s); - // Freezes the given set of handlers. You may not freeze a handler without - // also freezing any handlers they point to. + /* Freezes the given set of handlers. You may not freeze a handler without + * also freezing any handlers they point to. */ static bool Freeze(Handlers*const* handlers, int n, Status* s); static bool Freeze(const std::vector<Handlers*>& handlers, Status* s); - // Returns the msgdef associated with this handlers object. + /* Returns the msgdef associated with this handlers object. */ const MessageDef* message_def() const; - // Adds the given pointer and function to the list of cleanup functions that - // will be run when these handlers are freed. If this pointer has previously - // been registered, the function returns false and does nothing. + /* Adds the given pointer and function to the list of cleanup functions that + * will be run when these handlers are freed. If this pointer has previously + * been registered, the function returns false and does nothing. */ bool AddCleanup(void *ptr, upb_handlerfree *cleanup); - // Sets the startmsg handler for the message, which is defined as follows: - // - // bool startmsg(MyType* closure) { - // // Called when the message begins. Returns true if processing should - // // continue. - // return true; - // } + /* Sets the startmsg handler for the message, which is defined as follows: + * + * bool startmsg(MyType* closure) { + * // Called when the message begins. Returns true if processing should + * // continue. + * return true; + * } + */ bool SetStartMessageHandler(const StartMessageHandler& handler); - // Sets the endmsg handler for the message, which is defined as follows: - // - // bool endmsg(MyType* closure, upb_status *status) { - // // Called when processing of this message ends, whether in success or - // // failure. "status" indicates the final status of processing, and - // // can also be modified in-place to update the final status. - // } + /* Sets the endmsg handler for the message, which is defined as follows: + * + * bool endmsg(MyType* closure, upb_status *status) { + * // Called when processing of this message ends, whether in success or + * // failure. "status" indicates the final status of processing, and + * // can also be modified in-place to update the final status. + * } + */ bool SetEndMessageHandler(const EndMessageHandler& handler); - // Sets the value handler for the given field, which is defined as follows - // (this is for an int32 field; other field types will pass their native - // C/C++ type for "val"): - // - // bool OnValue(MyClosure* c, const MyHandlerData* d, int32_t val) { - // // Called when the field's value is encountered. "d" contains - // // whatever data was bound to this field when it was registered. - // // Returns true if processing should continue. - // return true; - // } - // - // handers->SetInt32Handler(f, UpbBind(OnValue, new MyHandlerData(...))); - // - // The value type must exactly match f->type(). - // For example, a handler that takes an int32_t parameter may only be used for - // fields of type UPB_TYPE_INT32 and UPB_TYPE_ENUM. - // - // Returns false if the handler failed to register; in this case the cleanup - // handler (if any) will be called immediately. + /* Sets the value handler for the given field, which is defined as follows + * (this is for an int32 field; other field types will pass their native + * C/C++ type for "val"): + * + * bool OnValue(MyClosure* c, const MyHandlerData* d, int32_t val) { + * // Called when the field's value is encountered. "d" contains + * // whatever data was bound to this field when it was registered. + * // Returns true if processing should continue. + * return true; + * } + * + * handers->SetInt32Handler(f, UpbBind(OnValue, new MyHandlerData(...))); + * + * The value type must exactly match f->type(). + * For example, a handler that takes an int32_t parameter may only be used for + * fields of type UPB_TYPE_INT32 and UPB_TYPE_ENUM. + * + * Returns false if the handler failed to register; in this case the cleanup + * handler (if any) will be called immediately. + */ bool SetInt32Handler (const FieldDef* f, const Int32Handler& h); bool SetInt64Handler (const FieldDef* f, const Int64Handler& h); bool SetUInt32Handler(const FieldDef* f, const UInt32Handler& h); @@ -4415,240 +3546,247 @@ UPB_DEFINE_CLASS1(upb::Handlers, upb::RefCounted, bool SetDoubleHandler(const FieldDef* f, const DoubleHandler& h); bool SetBoolHandler (const FieldDef* f, const BoolHandler& h); - // Like the previous, but templated on the type on the value (ie. int32). - // This is mostly useful to call from other templates. To call this you must - // specify the template parameter explicitly, ie: - // h->SetValueHandler<T>(f, UpbBind(MyHandler<T>, MyData)); + /* Like the previous, but templated on the type on the value (ie. int32). + * This is mostly useful to call from other templates. To call this you must + * specify the template parameter explicitly, ie: + * h->SetValueHandler<T>(f, UpbBind(MyHandler<T>, MyData)); */ template <class T> bool SetValueHandler( const FieldDef *f, const typename ValueHandler<typename CanonicalType<T>::Type>::H& handler); - // Sets handlers for a string field, which are defined as follows: - // - // MySubClosure* startstr(MyClosure* c, const MyHandlerData* d, - // size_t size_hint) { - // // Called when a string value begins. The return value indicates the - // // closure for the string. "size_hint" indicates the size of the - // // string if it is known, however if the string is length-delimited - // // and the end-of-string is not available size_hint will be zero. - // // This case is indistinguishable from the case where the size is - // // known to be zero. - // // - // // TODO(haberman): is it important to distinguish these cases? - // // If we had ssize_t as a type we could make -1 "unknown", but - // // ssize_t is POSIX (not ANSI) and therefore less portable. - // // In practice I suspect it won't be important to distinguish. - // return closure; - // } - // - // size_t str(MyClosure* closure, const MyHandlerData* d, - // const char *str, size_t len) { - // // Called for each buffer of string data; the multiple physical buffers - // // are all part of the same logical string. The return value indicates - // // how many bytes were consumed. If this number is less than "len", - // // this will also indicate that processing should be halted for now, - // // like returning false or UPB_BREAK from any other callback. If - // // number is greater than "len", the excess bytes will be skipped over - // // and not passed to the callback. - // return len; - // } - // - // bool endstr(MyClosure* c, const MyHandlerData* d) { - // // Called when a string value ends. Return value indicates whether - // // processing should continue. - // return true; - // } + /* Sets handlers for a string field, which are defined as follows: + * + * MySubClosure* startstr(MyClosure* c, const MyHandlerData* d, + * size_t size_hint) { + * // Called when a string value begins. The return value indicates the + * // closure for the string. "size_hint" indicates the size of the + * // string if it is known, however if the string is length-delimited + * // and the end-of-string is not available size_hint will be zero. + * // This case is indistinguishable from the case where the size is + * // known to be zero. + * // + * // TODO(haberman): is it important to distinguish these cases? + * // If we had ssize_t as a type we could make -1 "unknown", but + * // ssize_t is POSIX (not ANSI) and therefore less portable. + * // In practice I suspect it won't be important to distinguish. + * return closure; + * } + * + * size_t str(MyClosure* closure, const MyHandlerData* d, + * const char *str, size_t len) { + * // Called for each buffer of string data; the multiple physical buffers + * // are all part of the same logical string. The return value indicates + * // how many bytes were consumed. If this number is less than "len", + * // this will also indicate that processing should be halted for now, + * // like returning false or UPB_BREAK from any other callback. If + * // number is greater than "len", the excess bytes will be skipped over + * // and not passed to the callback. + * return len; + * } + * + * bool endstr(MyClosure* c, const MyHandlerData* d) { + * // Called when a string value ends. Return value indicates whether + * // processing should continue. + * return true; + * } + */ bool SetStartStringHandler(const FieldDef* f, const StartStringHandler& h); bool SetStringHandler(const FieldDef* f, const StringHandler& h); bool SetEndStringHandler(const FieldDef* f, const EndFieldHandler& h); - // Sets the startseq handler, which is defined as follows: - // - // MySubClosure *startseq(MyClosure* c, const MyHandlerData* d) { - // // Called when a sequence (repeated field) begins. The returned - // // pointer indicates the closure for the sequence (or UPB_BREAK - // // to interrupt processing). - // return closure; - // } - // - // h->SetStartSequenceHandler(f, UpbBind(startseq, new MyHandlerData(...))); - // - // Returns "false" if "f" does not belong to this message or is not a - // repeated field. + /* Sets the startseq handler, which is defined as follows: + * + * MySubClosure *startseq(MyClosure* c, const MyHandlerData* d) { + * // Called when a sequence (repeated field) begins. The returned + * // pointer indicates the closure for the sequence (or UPB_BREAK + * // to interrupt processing). + * return closure; + * } + * + * h->SetStartSequenceHandler(f, UpbBind(startseq, new MyHandlerData(...))); + * + * Returns "false" if "f" does not belong to this message or is not a + * repeated field. + */ bool SetStartSequenceHandler(const FieldDef* f, const StartFieldHandler& h); - // Sets the startsubmsg handler for the given field, which is defined as - // follows: - // - // MySubClosure* startsubmsg(MyClosure* c, const MyHandlerData* d) { - // // Called when a submessage begins. The returned pointer indicates the - // // closure for the sequence (or UPB_BREAK to interrupt processing). - // return closure; - // } - // - // h->SetStartSubMessageHandler(f, UpbBind(startsubmsg, - // new MyHandlerData(...))); - // - // Returns "false" if "f" does not belong to this message or is not a - // submessage/group field. + /* Sets the startsubmsg handler for the given field, which is defined as + * follows: + * + * MySubClosure* startsubmsg(MyClosure* c, const MyHandlerData* d) { + * // Called when a submessage begins. The returned pointer indicates the + * // closure for the sequence (or UPB_BREAK to interrupt processing). + * return closure; + * } + * + * h->SetStartSubMessageHandler(f, UpbBind(startsubmsg, + * new MyHandlerData(...))); + * + * Returns "false" if "f" does not belong to this message or is not a + * submessage/group field. + */ bool SetStartSubMessageHandler(const FieldDef* f, const StartFieldHandler& h); - // Sets the endsubmsg handler for the given field, which is defined as - // follows: - // - // bool endsubmsg(MyClosure* c, const MyHandlerData* d) { - // // Called when a submessage ends. Returns true to continue processing. - // return true; - // } - // - // Returns "false" if "f" does not belong to this message or is not a - // submessage/group field. + /* Sets the endsubmsg handler for the given field, which is defined as + * follows: + * + * bool endsubmsg(MyClosure* c, const MyHandlerData* d) { + * // Called when a submessage ends. Returns true to continue processing. + * return true; + * } + * + * Returns "false" if "f" does not belong to this message or is not a + * submessage/group field. + */ bool SetEndSubMessageHandler(const FieldDef *f, const EndFieldHandler &h); - // Starts the endsubseq handler for the given field, which is defined as - // follows: - // - // bool endseq(MyClosure* c, const MyHandlerData* d) { - // // Called when a sequence ends. Returns true continue processing. - // return true; - // } - // - // Returns "false" if "f" does not belong to this message or is not a - // repeated field. + /* Starts the endsubseq handler for the given field, which is defined as + * follows: + * + * bool endseq(MyClosure* c, const MyHandlerData* d) { + * // Called when a sequence ends. Returns true continue processing. + * return true; + * } + * + * Returns "false" if "f" does not belong to this message or is not a + * repeated field. + */ bool SetEndSequenceHandler(const FieldDef* f, const EndFieldHandler& h); - // Sets or gets the object that specifies handlers for the given field, which - // must be a submessage or group. Returns NULL if no handlers are set. + /* Sets or gets the object that specifies handlers for the given field, which + * must be a submessage or group. Returns NULL if no handlers are set. */ bool SetSubHandlers(const FieldDef* f, const Handlers* sub); const Handlers* GetSubHandlers(const FieldDef* f) const; - // Equivalent to GetSubHandlers, but takes the STARTSUBMSG selector for the - // field. + /* Equivalent to GetSubHandlers, but takes the STARTSUBMSG selector for the + * field. */ const Handlers* GetSubHandlers(Selector startsubmsg) const; - // A selector refers to a specific field handler in the Handlers object - // (for example: the STARTSUBMSG handler for field "field15"). - // On success, returns true and stores the selector in "s". - // If the FieldDef or Type are invalid, returns false. - // The returned selector is ONLY valid for Handlers whose MessageDef - // contains this FieldDef. + /* A selector refers to a specific field handler in the Handlers object + * (for example: the STARTSUBMSG handler for field "field15"). + * On success, returns true and stores the selector in "s". + * If the FieldDef or Type are invalid, returns false. + * The returned selector is ONLY valid for Handlers whose MessageDef + * contains this FieldDef. */ static bool GetSelector(const FieldDef* f, Type type, Selector* s); - // Given a START selector of any kind, returns the corresponding END selector. + /* Given a START selector of any kind, returns the corresponding END selector. */ static Selector GetEndSelector(Selector start_selector); - // Returns the function pointer for this handler. It is the client's - // responsibility to cast to the correct function type before calling it. + /* Returns the function pointer for this handler. It is the client's + * responsibility to cast to the correct function type before calling it. */ GenericFunction* GetHandler(Selector selector); - // Sets the given attributes to the attributes for this selector. + /* Sets the given attributes to the attributes for this selector. */ bool GetAttributes(Selector selector, HandlerAttributes* attr); - // Returns the handler data that was registered with this handler. + /* Returns the handler data that was registered with this handler. */ const void* GetHandlerData(Selector selector); - // Could add any of the following functions as-needed, with some minor - // implementation changes: - // - // const FieldDef* GetFieldDef(Selector selector); - // static bool IsSequence(Selector selector); + /* Could add any of the following functions as-needed, with some minor + * implementation changes: + * + * const FieldDef* GetFieldDef(Selector selector); + * static bool IsSequence(Selector selector); */ private: - UPB_DISALLOW_POD_OPS(Handlers, upb::Handlers); + UPB_DISALLOW_POD_OPS(Handlers, upb::Handlers) friend UPB_INLINE GenericFunction *::upb_handlers_gethandler( const upb_handlers *h, upb_selector_t s); friend UPB_INLINE const void *::upb_handlers_gethandlerdata( const upb_handlers *h, upb_selector_t s); +#else +struct upb_handlers { +#endif + upb_refcounted base; -, -UPB_DEFINE_STRUCT(upb_handlers, upb_refcounted, const upb_msgdef *msg; const upb_handlers **sub; const void *top_closure_type; upb_inttable cleanup_; - upb_status status_; // Used only when mutable. - upb_handlers_tabent table[1]; // Dynamically-sized field handler array. -)); - + upb_status status_; /* Used only when mutable. */ + upb_handlers_tabent table[1]; /* Dynamically-sized field handler array. */ +}; #ifdef __cplusplus namespace upb { -// Convenience macros for creating a Handler object that is wrapped with a -// type-safe wrapper function that converts the "void*" parameters/returns -// of the underlying C API into nice C++ function. -// -// Sample usage: -// void OnValue1(MyClosure* c, const MyHandlerData* d, int32_t val) { -// // do stuff ... -// } -// -// // Handler that doesn't need any data bound to it. -// void OnValue2(MyClosure* c, int32_t val) { -// // do stuff ... -// } -// -// // Handler that returns bool so it can return failure if necessary. -// bool OnValue3(MyClosure* c, int32_t val) { -// // do stuff ... -// return ok; -// } -// -// // Member function handler. -// class MyClosure { -// public: -// void OnValue(int32_t val) { -// // do stuff ... -// } -// }; -// -// // Takes ownership of the MyHandlerData. -// handlers->SetInt32Handler(f1, UpbBind(OnValue1, new MyHandlerData(...))); -// handlers->SetInt32Handler(f2, UpbMakeHandler(OnValue2)); -// handlers->SetInt32Handler(f1, UpbMakeHandler(OnValue3)); -// handlers->SetInt32Handler(f2, UpbMakeHandler(&MyClosure::OnValue)); +/* Convenience macros for creating a Handler object that is wrapped with a + * type-safe wrapper function that converts the "void*" parameters/returns + * of the underlying C API into nice C++ function. + * + * Sample usage: + * void OnValue1(MyClosure* c, const MyHandlerData* d, int32_t val) { + * // do stuff ... + * } + * + * // Handler that doesn't need any data bound to it. + * void OnValue2(MyClosure* c, int32_t val) { + * // do stuff ... + * } + * + * // Handler that returns bool so it can return failure if necessary. + * bool OnValue3(MyClosure* c, int32_t val) { + * // do stuff ... + * return ok; + * } + * + * // Member function handler. + * class MyClosure { + * public: + * void OnValue(int32_t val) { + * // do stuff ... + * } + * }; + * + * // Takes ownership of the MyHandlerData. + * handlers->SetInt32Handler(f1, UpbBind(OnValue1, new MyHandlerData(...))); + * handlers->SetInt32Handler(f2, UpbMakeHandler(OnValue2)); + * handlers->SetInt32Handler(f1, UpbMakeHandler(OnValue3)); + * handlers->SetInt32Handler(f2, UpbMakeHandler(&MyClosure::OnValue)); + */ #ifdef UPB_CXX11 -// In C++11, the "template" disambiguator can appear even outside templates, -// so all calls can safely use this pair of macros. +/* In C++11, the "template" disambiguator can appear even outside templates, + * so all calls can safely use this pair of macros. */ #define UpbMakeHandler(f) upb::MatchFunc(f).template GetFunc<f>() -// We have to be careful to only evaluate "d" once. +/* We have to be careful to only evaluate "d" once. */ #define UpbBind(f, d) upb::MatchFunc(f).template GetFunc<f>((d)) #else -// Prior to C++11, the "template" disambiguator may only appear inside a -// template, so the regular macro must not use "template" +/* Prior to C++11, the "template" disambiguator may only appear inside a + * template, so the regular macro must not use "template" */ #define UpbMakeHandler(f) upb::MatchFunc(f).GetFunc<f>() #define UpbBind(f, d) upb::MatchFunc(f).GetFunc<f>((d)) -#endif // UPB_CXX11 +#endif /* UPB_CXX11 */ -// This macro must be used in C++98 for calls from inside a template. But we -// define this variant in all cases; code that wants to be compatible with both -// C++98 and C++11 should always use this macro when calling from a template. +/* This macro must be used in C++98 for calls from inside a template. But we + * define this variant in all cases; code that wants to be compatible with both + * C++98 and C++11 should always use this macro when calling from a template. */ #define UpbMakeHandlerT(f) upb::MatchFunc(f).template GetFunc<f>() -// We have to be careful to only evaluate "d" once. +/* We have to be careful to only evaluate "d" once. */ #define UpbBindT(f, d) upb::MatchFunc(f).template GetFunc<f>((d)) -// Handler: a struct that contains the (handler, data, deleter) tuple that is -// used to register all handlers. Users can Make() these directly but it's -// more convenient to use the UpbMakeHandler/UpbBind macros above. +/* Handler: a struct that contains the (handler, data, deleter) tuple that is + * used to register all handlers. Users can Make() these directly but it's + * more convenient to use the UpbMakeHandler/UpbBind macros above. */ template <class T> class Handler { public: - // The underlying, handler function signature that upb uses internally. + /* The underlying, handler function signature that upb uses internally. */ typedef T FuncPtr; - // Intentionally implicit. + /* Intentionally implicit. */ template <class F> Handler(F func); ~Handler(); @@ -4660,7 +3798,7 @@ template <class T> class Handler { } } - UPB_DISALLOW_COPY_AND_ASSIGN(Handler); + UPB_DISALLOW_COPY_AND_ASSIGN(Handler) friend class Handlers; FuncPtr handler_; mutable HandlerAttributes attr_; @@ -4669,15 +3807,15 @@ template <class T> class Handler { upb_handlerfree *cleanup_func_; }; -} // namespace upb +} /* namespace upb */ -#endif // __cplusplus +#endif /* __cplusplus */ UPB_BEGIN_EXTERN_C -// Native C API. +/* Native C API. */ -// Handler function typedefs. +/* Handler function typedefs. */ typedef bool upb_startmsg_handlerfunc(void *c, const void*); typedef bool upb_endmsg_handlerfunc(void *c, const void *, upb_status *status); typedef void* upb_startfield_handlerfunc(void *c, const void *hd); @@ -4694,10 +3832,10 @@ typedef void *upb_startstr_handlerfunc(void *c, const void *hd, typedef size_t upb_string_handlerfunc(void *c, const void *hd, const char *buf, size_t n, const upb_bufhandle* handle); -// upb_bufhandle +/* upb_bufhandle */ size_t upb_bufhandle_objofs(const upb_bufhandle *h); -// upb_handlerattr +/* upb_handlerattr */ void upb_handlerattr_init(upb_handlerattr *attr); void upb_handlerattr_uninit(upb_handlerattr *attr); @@ -4715,7 +3853,7 @@ UPB_INLINE const void *upb_handlerattr_handlerdata( return attr->handler_data_; } -// upb_handlers +/* upb_handlers */ typedef void upb_handlers_callback(const void *closure, upb_handlers *h); upb_handlers *upb_handlers_new(const upb_msgdef *m, const void *owner); @@ -4723,12 +3861,9 @@ const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m, const void *owner, upb_handlers_callback *callback, const void *closure); -bool upb_handlers_isfrozen(const upb_handlers *h); -void upb_handlers_ref(const upb_handlers *h, const void *owner); -void upb_handlers_unref(const upb_handlers *h, const void *owner); -void upb_handlers_donateref(const upb_handlers *h, const void *from, - const void *to); -void upb_handlers_checkref(const upb_handlers *h, const void *owner); + +/* Include refcounted methods like upb_handlers_ref(). */ +UPB_REFCOUNTED_CMETHODS(upb_handlers, upb_handlers_upcast) const upb_status *upb_handlers_status(upb_handlers *h); void upb_handlers_clearerr(upb_handlers *h); @@ -4799,26 +3934,29 @@ UPB_INLINE const void *upb_handlers_gethandlerdata(const upb_handlers *h, return upb_handlerattr_handlerdata(&h->table[s].attr); } -// Handler types for single fields. -// Right now we only have one for TYPE_BYTES but ones for other types -// should follow. -// -// These follow the same handlers protocol for fields of a message. -UPB_DEFINE_CLASS0(upb::BytesHandler, +#ifdef __cplusplus + +/* Handler types for single fields. + * Right now we only have one for TYPE_BYTES but ones for other types + * should follow. + * + * These follow the same handlers protocol for fields of a message. */ +class upb::BytesHandler { public: BytesHandler(); ~BytesHandler(); -, -UPB_DEFINE_STRUCT0(upb_byteshandler, +#else +struct upb_byteshandler { +#endif upb_handlers_tabent table[3]; -)); +}; void upb_byteshandler_init(upb_byteshandler *h); -// Caller must ensure that "d" outlives the handlers. -// TODO(haberman): should this have a "freeze" operation? It's not necessary -// for memory management, but could be useful to force immutability and provide -// a convenient moment to verify that all registration succeeded. +/* Caller must ensure that "d" outlives the handlers. + * TODO(haberman): should this have a "freeze" operation? It's not necessary + * for memory management, but could be useful to force immutability and provide + * a convenient moment to verify that all registration succeeded. */ bool upb_byteshandler_setstartstr(upb_byteshandler *h, upb_startstr_handlerfunc *func, void *d); bool upb_byteshandler_setstring(upb_byteshandler *h, @@ -4826,7 +3964,7 @@ bool upb_byteshandler_setstring(upb_byteshandler *h, bool upb_byteshandler_setendstr(upb_byteshandler *h, upb_endfield_handlerfunc *func, void *d); -// "Static" methods +/* "Static" methods */ bool upb_handlers_freeze(upb_handlers *const *handlers, int n, upb_status *s); upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f); bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type, @@ -4835,7 +3973,7 @@ UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) { return start + 1; } -// Internal-only. +/* Internal-only. */ uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f); uint32_t upb_handlers_selectorcount(const upb_fielddef *f); @@ -4856,21 +3994,56 @@ UPB_END_EXTERN_C #include <limits.h> -// Type detection and typedefs for integer types. -// For platforms where there are multiple 32-bit or 64-bit types, we need to be -// able to enumerate them so we can properly create overloads for all variants. -// -// If any platform existed where there were three integer types with the same -// size, this would have to become more complicated. For example, short, int, -// and long could all be 32-bits. Even more diabolically, short, int, long, -// and long long could all be 64 bits and still be standard-compliant. -// However, few platforms are this strange, and it's unlikely that upb will be -// used on the strangest ones. - -// Can't count on stdint.h limits like INT32_MAX, because in C++ these are -// only defined when __STDC_LIMIT_MACROS are defined before the *first* include -// of stdint.h. We can't guarantee that someone else didn't include these first -// without defining __STDC_LIMIT_MACROS. +/* C inline methods. */ + +/* upb_bufhandle */ +UPB_INLINE void upb_bufhandle_init(upb_bufhandle *h) { + h->obj_ = NULL; + h->objtype_ = NULL; + h->buf_ = NULL; + h->objofs_ = 0; +} +UPB_INLINE void upb_bufhandle_uninit(upb_bufhandle *h) { + UPB_UNUSED(h); +} +UPB_INLINE void upb_bufhandle_setobj(upb_bufhandle *h, const void *obj, + const void *type) { + h->obj_ = obj; + h->objtype_ = type; +} +UPB_INLINE void upb_bufhandle_setbuf(upb_bufhandle *h, const char *buf, + size_t ofs) { + h->buf_ = buf; + h->objofs_ = ofs; +} +UPB_INLINE const void *upb_bufhandle_obj(const upb_bufhandle *h) { + return h->obj_; +} +UPB_INLINE const void *upb_bufhandle_objtype(const upb_bufhandle *h) { + return h->objtype_; +} +UPB_INLINE const char *upb_bufhandle_buf(const upb_bufhandle *h) { + return h->buf_; +} + + +#ifdef __cplusplus + +/* Type detection and typedefs for integer types. + * For platforms where there are multiple 32-bit or 64-bit types, we need to be + * able to enumerate them so we can properly create overloads for all variants. + * + * If any platform existed where there were three integer types with the same + * size, this would have to become more complicated. For example, short, int, + * and long could all be 32-bits. Even more diabolically, short, int, long, + * and long long could all be 64 bits and still be standard-compliant. + * However, few platforms are this strange, and it's unlikely that upb will be + * used on the strangest ones. */ + +/* Can't count on stdint.h limits like INT32_MAX, because in C++ these are + * only defined when __STDC_LIMIT_MACROS are defined before the *first* include + * of stdint.h. We can't guarantee that someone else didn't include these first + * without defining __STDC_LIMIT_MACROS. */ #define UPB_INT32_MAX 0x7fffffffLL #define UPB_INT32_MIN (-UPB_INT32_MAX - 1) #define UPB_INT64_MAX 0x7fffffffffffffffLL @@ -4892,8 +4065,8 @@ UPB_END_EXTERN_C #define UPB_LLONG_IS_64BITS 1 #endif -// We use macros instead of typedefs so we can undefine them later and avoid -// leaking them outside this header file. +/* We use macros instead of typedefs so we can undefine them later and avoid + * leaking them outside this header file. */ #if UPB_INT_IS_32BITS #define UPB_INT32_T int #define UPB_UINT32_T unsigned int @@ -4902,12 +4075,12 @@ UPB_END_EXTERN_C #define UPB_TWO_32BIT_TYPES 1 #define UPB_INT32ALT_T long #define UPB_UINT32ALT_T unsigned long -#endif // UPB_LONG_IS_32BITS +#endif /* UPB_LONG_IS_32BITS */ -#elif UPB_LONG_IS_32BITS // && !UPB_INT_IS_32BITS +#elif UPB_LONG_IS_32BITS /* && !UPB_INT_IS_32BITS */ #define UPB_INT32_T long #define UPB_UINT32_T unsigned long -#endif // UPB_INT_IS_32BITS +#endif /* UPB_INT_IS_32BITS */ #if UPB_LONG_IS_64BITS @@ -4918,12 +4091,12 @@ UPB_END_EXTERN_C #define UPB_TWO_64BIT_TYPES 1 #define UPB_INT64ALT_T long long #define UPB_UINT64ALT_T unsigned long long -#endif // UPB_LLONG_IS_64BITS +#endif /* UPB_LLONG_IS_64BITS */ -#elif UPB_LLONG_IS_64BITS // && !UPB_LONG_IS_64BITS +#elif UPB_LLONG_IS_64BITS /* && !UPB_LONG_IS_64BITS */ #define UPB_INT64_T long long #define UPB_UINT64_T unsigned long long -#endif // UPB_LONG_IS_64BITS +#endif /* UPB_LONG_IS_64BITS */ #undef UPB_INT32_MAX #undef UPB_INT32_MIN @@ -4934,56 +4107,22 @@ UPB_END_EXTERN_C #undef UPB_LONG_IS_64BITS #undef UPB_LLONG_IS_64BITS -// C inline methods. - -// upb_bufhandle -UPB_INLINE void upb_bufhandle_init(upb_bufhandle *h) { - h->obj_ = NULL; - h->objtype_ = NULL; - h->buf_ = NULL; - h->objofs_ = 0; -} -UPB_INLINE void upb_bufhandle_uninit(upb_bufhandle *h) { - UPB_UNUSED(h); -} -UPB_INLINE void upb_bufhandle_setobj(upb_bufhandle *h, const void *obj, - const void *type) { - h->obj_ = obj; - h->objtype_ = type; -} -UPB_INLINE void upb_bufhandle_setbuf(upb_bufhandle *h, const char *buf, - size_t ofs) { - h->buf_ = buf; - h->objofs_ = ofs; -} -UPB_INLINE const void *upb_bufhandle_obj(const upb_bufhandle *h) { - return h->obj_; -} -UPB_INLINE const void *upb_bufhandle_objtype(const upb_bufhandle *h) { - return h->objtype_; -} -UPB_INLINE const char *upb_bufhandle_buf(const upb_bufhandle *h) { - return h->buf_; -} - - -#ifdef __cplusplus namespace upb { typedef void CleanupFunc(void *ptr); -// Template to remove "const" from "const T*" and just return "T*". -// -// We define a nonsense default because otherwise it will fail to instantiate as -// a function parameter type even in cases where we don't expect any caller to -// actually match the overload. +/* Template to remove "const" from "const T*" and just return "T*". + * + * We define a nonsense default because otherwise it will fail to instantiate as + * a function parameter type even in cases where we don't expect any caller to + * actually match the overload. */ class CouldntRemoveConst {}; template <class T> struct remove_constptr { typedef CouldntRemoveConst type; }; template <class T> struct remove_constptr<const T *> { typedef T *type; }; -// Template that we use below to remove a template specialization from -// consideration if it matches a specific type. +/* Template that we use below to remove a template specialization from + * consideration if it matches a specific type. */ template <class T, class U> struct disable_if_same { typedef void Type; }; template <class T> struct disable_if_same<T, T> {}; @@ -5020,27 +4159,27 @@ bool is_same<T, U>::value = false; template<class T> bool is_same<T, T>::value = true; -// FuncInfo //////////////////////////////////////////////////////////////////// +/* FuncInfo *******************************************************************/ -// Info about the user's original, pre-wrapped function. +/* Info about the user's original, pre-wrapped function. */ template <class C, class R = void> struct FuncInfo { - // The type of the closure that the function takes (its first param). + /* The type of the closure that the function takes (its first param). */ typedef C Closure; - // The return type. + /* The return type. */ typedef R Return; }; -// Func //////////////////////////////////////////////////////////////////////// +/* Func ***********************************************************************/ -// Func1, Func2, Func3: Template classes representing a function and its -// signature. -// -// Since the function is a template parameter, calling the function can be -// inlined at compile-time and does not require a function pointer at runtime. -// These functions are not bound to a handler data so have no data or cleanup -// handler. +/* Func1, Func2, Func3: Template classes representing a function and its + * signature. + * + * Since the function is a template parameter, calling the function can be + * inlined at compile-time and does not require a function pointer at runtime. + * These functions are not bound to a handler data so have no data or cleanup + * handler. */ struct UnboundFunc { CleanupFunc *GetCleanup() { return NULL; } void *GetData() { return NULL; } @@ -5085,13 +4224,13 @@ struct Func5 : public UnboundFunc { } }; -// BoundFunc /////////////////////////////////////////////////////////////////// +/* BoundFunc ******************************************************************/ -// BoundFunc2, BoundFunc3: Like Func2/Func3 except also contains a value that -// shall be bound to the function's second parameter. -// -// Note that the second parameter is a const pointer, but our stored bound value -// is non-const so we can free it when the handlers are destroyed. +/* BoundFunc2, BoundFunc3: Like Func2/Func3 except also contains a value that + * shall be bound to the function's second parameter. + * + * Note that the second parameter is a const pointer, but our stored bound value + * is non-const so we can free it when the handlers are destroyed. */ template <class T> struct BoundFunc { typedef typename remove_constptr<T>::type MutableP2; @@ -5131,13 +4270,13 @@ struct BoundFunc5 : public BoundFunc<P2> { explicit BoundFunc5(typename Base::MutableP2 arg) : Base(arg) {} }; -// FuncSig ///////////////////////////////////////////////////////////////////// +/* FuncSig ********************************************************************/ -// FuncSig1, FuncSig2, FuncSig3: template classes reflecting a function -// *signature*, but without a specific function attached. -// -// These classes contain member functions that can be invoked with a -// specific function to return a Func/BoundFunc class. +/* FuncSig1, FuncSig2, FuncSig3: template classes reflecting a function + * *signature*, but without a specific function attached. + * + * These classes contain member functions that can be invoked with a + * specific function to return a Func/BoundFunc class. */ template <class R, class P1> struct FuncSig1 { template <R F(P1)> @@ -5202,41 +4341,41 @@ struct FuncSig5 { } }; -// Overloaded template function that can construct the appropriate FuncSig* -// class given a function pointer by deducing the template parameters. +/* Overloaded template function that can construct the appropriate FuncSig* + * class given a function pointer by deducing the template parameters. */ template <class R, class P1> inline FuncSig1<R, P1> MatchFunc(R (*f)(P1)) { - UPB_UNUSED(f); // Only used for template parameter deduction. + UPB_UNUSED(f); /* Only used for template parameter deduction. */ return FuncSig1<R, P1>(); } template <class R, class P1, class P2> inline FuncSig2<R, P1, P2> MatchFunc(R (*f)(P1, P2)) { - UPB_UNUSED(f); // Only used for template parameter deduction. + UPB_UNUSED(f); /* Only used for template parameter deduction. */ return FuncSig2<R, P1, P2>(); } template <class R, class P1, class P2, class P3> inline FuncSig3<R, P1, P2, P3> MatchFunc(R (*f)(P1, P2, P3)) { - UPB_UNUSED(f); // Only used for template parameter deduction. + UPB_UNUSED(f); /* Only used for template parameter deduction. */ return FuncSig3<R, P1, P2, P3>(); } template <class R, class P1, class P2, class P3, class P4> inline FuncSig4<R, P1, P2, P3, P4> MatchFunc(R (*f)(P1, P2, P3, P4)) { - UPB_UNUSED(f); // Only used for template parameter deduction. + UPB_UNUSED(f); /* Only used for template parameter deduction. */ return FuncSig4<R, P1, P2, P3, P4>(); } template <class R, class P1, class P2, class P3, class P4, class P5> inline FuncSig5<R, P1, P2, P3, P4, P5> MatchFunc(R (*f)(P1, P2, P3, P4, P5)) { - UPB_UNUSED(f); // Only used for template parameter deduction. + UPB_UNUSED(f); /* Only used for template parameter deduction. */ return FuncSig5<R, P1, P2, P3, P4, P5>(); } -// MethodSig /////////////////////////////////////////////////////////////////// +/* MethodSig ******************************************************************/ -// CallMethod*: a function template that calls a given method. +/* CallMethod*: a function template that calls a given method. */ template <class R, class C, R (C::*F)()> R CallMethod0(C *obj) { return ((*obj).*F)(); @@ -5263,10 +4402,10 @@ R CallMethod4(C *obj, P1 arg1, P2 arg2, P3 arg3, P4 arg4) { return ((*obj).*F)(arg1, arg2, arg3, arg4); } -// MethodSig: like FuncSig, but for member functions. -// -// GetFunc() returns a normal FuncN object, so after calling GetFunc() no -// more logic is required to special-case methods. +/* MethodSig: like FuncSig, but for member functions. + * + * GetFunc() returns a normal FuncN object, so after calling GetFunc() no + * more logic is required to special-case methods. */ template <class R, class C> struct MethodSig0 { template <R (C::*F)()> @@ -5347,61 +4486,61 @@ struct MethodSig4 { template <class R, class C> inline MethodSig0<R, C> MatchFunc(R (C::*f)()) { - UPB_UNUSED(f); // Only used for template parameter deduction. + UPB_UNUSED(f); /* Only used for template parameter deduction. */ return MethodSig0<R, C>(); } template <class R, class C, class P1> inline MethodSig1<R, C, P1> MatchFunc(R (C::*f)(P1)) { - UPB_UNUSED(f); // Only used for template parameter deduction. + UPB_UNUSED(f); /* Only used for template parameter deduction. */ return MethodSig1<R, C, P1>(); } template <class R, class C, class P1, class P2> inline MethodSig2<R, C, P1, P2> MatchFunc(R (C::*f)(P1, P2)) { - UPB_UNUSED(f); // Only used for template parameter deduction. + UPB_UNUSED(f); /* Only used for template parameter deduction. */ return MethodSig2<R, C, P1, P2>(); } template <class R, class C, class P1, class P2, class P3> inline MethodSig3<R, C, P1, P2, P3> MatchFunc(R (C::*f)(P1, P2, P3)) { - UPB_UNUSED(f); // Only used for template parameter deduction. + UPB_UNUSED(f); /* Only used for template parameter deduction. */ return MethodSig3<R, C, P1, P2, P3>(); } template <class R, class C, class P1, class P2, class P3, class P4> inline MethodSig4<R, C, P1, P2, P3, P4> MatchFunc(R (C::*f)(P1, P2, P3, P4)) { - UPB_UNUSED(f); // Only used for template parameter deduction. + UPB_UNUSED(f); /* Only used for template parameter deduction. */ return MethodSig4<R, C, P1, P2, P3, P4>(); } -// MaybeWrapReturn ///////////////////////////////////////////////////////////// +/* MaybeWrapReturn ************************************************************/ -// Template class that attempts to wrap the return value of the function so it -// matches the expected type. There are two main adjustments it may make: -// -// 1. If the function returns void, make it return the expected type and with -// a value that always indicates success. -// 2. If the function returns bool, make it return the expected type with a -// value that indicates success or failure. -// -// The "expected type" for return is: -// 1. void* for start handlers. If the closure parameter has a different type -// we will cast it to void* for the return in the success case. -// 2. size_t for string buffer handlers. -// 3. bool for everything else. +/* Template class that attempts to wrap the return value of the function so it + * matches the expected type. There are two main adjustments it may make: + * + * 1. If the function returns void, make it return the expected type and with + * a value that always indicates success. + * 2. If the function returns bool, make it return the expected type with a + * value that indicates success or failure. + * + * The "expected type" for return is: + * 1. void* for start handlers. If the closure parameter has a different type + * we will cast it to void* for the return in the success case. + * 2. size_t for string buffer handlers. + * 3. bool for everything else. */ -// Template parameters are FuncN type and desired return type. +/* Template parameters are FuncN type and desired return type. */ template <class F, class R, class Enable = void> struct MaybeWrapReturn; -// If the return type matches, return the given function unwrapped. +/* If the return type matches, return the given function unwrapped. */ template <class F> struct MaybeWrapReturn<F, typename F::Return> { typedef F Func; }; -// Function wrapper that munges the return value from void to (bool)true. +/* Function wrapper that munges the return value from void to (bool)true. */ template <class P1, class P2, void F(P1, P2)> bool ReturnTrue2(P1 p1, P2 p2) { F(p1, p2); @@ -5414,7 +4553,7 @@ bool ReturnTrue3(P1 p1, P2 p2, P3 p3) { return true; } -// Function wrapper that munges the return value from void to (void*)arg1 +/* Function wrapper that munges the return value from void to (void*)arg1 */ template <class P1, class P2, void F(P1, P2)> void *ReturnClosure2(P1 p1, P2 p2) { F(p1, p2); @@ -5427,7 +4566,7 @@ void *ReturnClosure3(P1 p1, P2 p2, P3 p3) { return p1; } -// Function wrapper that munges the return value from R to void*. +/* Function wrapper that munges the return value from R to void*. */ template <class R, class P1, class P2, R F(P1, P2)> void *CastReturnToVoidPtr2(P1 p1, P2 p2) { return F(p1, p2); @@ -5438,7 +4577,7 @@ void *CastReturnToVoidPtr3(P1 p1, P2 p2, P3 p3) { return F(p1, p2, p3); } -// Function wrapper that munges the return value from bool to void*. +/* Function wrapper that munges the return value from bool to void*. */ template <class P1, class P2, bool F(P1, P2)> void *ReturnClosureOrBreak2(P1 p1, P2 p2) { return F(p1, p2) ? p1 : UPB_BREAK; @@ -5449,7 +4588,7 @@ void *ReturnClosureOrBreak3(P1 p1, P2 p2, P3 p3) { return F(p1, p2, p3) ? p1 : UPB_BREAK; } -// For the string callback, which takes five params, returns the size param. +/* For the string callback, which takes five params, returns the size param. */ template <class P1, class P2, void F(P1, P2, const char *, size_t, const BufferHandle *)> size_t ReturnStringLen(P1 p1, P2 p2, const char *p3, size_t p4, @@ -5458,8 +4597,8 @@ size_t ReturnStringLen(P1 p1, P2 p2, const char *p3, size_t p4, return p4; } -// For the string callback, which takes five params, returns the size param or -// zero. +/* For the string callback, which takes five params, returns the size param or + * zero. */ template <class P1, class P2, bool F(P1, P2, const char *, size_t, const BufferHandle *)> size_t ReturnNOr0(P1 p1, P2 p2, const char *p3, size_t p4, @@ -5467,8 +4606,8 @@ size_t ReturnNOr0(P1 p1, P2 p2, const char *p3, size_t p4, return F(p1, p2, p3, p4, p5) ? p4 : 0; } -// If we have a function returning void but want a function returning bool, wrap -// it in a function that returns true. +/* If we have a function returning void but want a function returning bool, wrap + * it in a function that returns true. */ template <class P1, class P2, void F(P1, P2), class I> struct MaybeWrapReturn<Func2<void, P1, P2, F, I>, bool> { typedef Func2<bool, P1, P2, ReturnTrue2<P1, P2, F>, I> Func; @@ -5479,8 +4618,8 @@ struct MaybeWrapReturn<Func3<void, P1, P2, P3, F, I>, bool> { typedef Func3<bool, P1, P2, P3, ReturnTrue3<P1, P2, P3, F>, I> Func; }; -// If our function returns void but we want one returning void*, wrap it in a -// function that returns the first argument. +/* If our function returns void but we want one returning void*, wrap it in a + * function that returns the first argument. */ template <class P1, class P2, void F(P1, P2), class I> struct MaybeWrapReturn<Func2<void, P1, P2, F, I>, void *> { typedef Func2<void *, P1, P2, ReturnClosure2<P1, P2, F>, I> Func; @@ -5491,8 +4630,8 @@ struct MaybeWrapReturn<Func3<void, P1, P2, P3, F, I>, void *> { typedef Func3<void *, P1, P2, P3, ReturnClosure3<P1, P2, P3, F>, I> Func; }; -// If our function returns R* but we want one returning void*, wrap it in a -// function that casts to void*. +/* If our function returns R* but we want one returning void*, wrap it in a + * function that casts to void*. */ template <class R, class P1, class P2, R *F(P1, P2), class I> struct MaybeWrapReturn<Func2<R *, P1, P2, F, I>, void *, typename disable_if_same<R *, void *>::Type> { @@ -5506,8 +4645,8 @@ struct MaybeWrapReturn<Func3<R *, P1, P2, P3, F, I>, void *, Func; }; -// If our function returns bool but we want one returning void*, wrap it in a -// function that returns either the first param or UPB_BREAK. +/* If our function returns bool but we want one returning void*, wrap it in a + * function that returns either the first param or UPB_BREAK. */ template <class P1, class P2, bool F(P1, P2), class I> struct MaybeWrapReturn<Func2<bool, P1, P2, F, I>, void *> { typedef Func2<void *, P1, P2, ReturnClosureOrBreak2<P1, P2, F>, I> Func; @@ -5519,8 +4658,8 @@ struct MaybeWrapReturn<Func3<bool, P1, P2, P3, F, I>, void *> { Func; }; -// If our function returns void but we want one returning size_t, wrap it in a -// function that returns the size argument. +/* If our function returns void but we want one returning size_t, wrap it in a + * function that returns the size argument. */ template <class P1, class P2, void F(P1, P2, const char *, size_t, const BufferHandle *), class I> struct MaybeWrapReturn< @@ -5530,8 +4669,8 @@ struct MaybeWrapReturn< ReturnStringLen<P1, P2, F>, I> Func; }; -// If our function returns bool but we want one returning size_t, wrap it in a -// function that returns either 0 or the buf size. +/* If our function returns bool but we want one returning size_t, wrap it in a + * function that returns either 0 or the buf size. */ template <class P1, class P2, bool F(P1, P2, const char *, size_t, const BufferHandle *), class I> struct MaybeWrapReturn< @@ -5541,16 +4680,16 @@ struct MaybeWrapReturn< ReturnNOr0<P1, P2, F>, I> Func; }; -// ConvertParams /////////////////////////////////////////////////////////////// +/* ConvertParams **************************************************************/ -// Template class that converts the function parameters if necessary, and -// ignores the HandlerData parameter if appropriate. -// -// Template parameter is the are FuncN function type. +/* Template class that converts the function parameters if necessary, and + * ignores the HandlerData parameter if appropriate. + * + * Template parameter is the are FuncN function type. */ template <class F, class T> struct ConvertParams; -// Function that discards the handler data parameter. +/* Function that discards the handler data parameter. */ template <class R, class P1, R F(P1)> R IgnoreHandlerData2(void *p1, const void *hd) { UPB_UNUSED(hd); @@ -5584,7 +4723,7 @@ R IgnoreHandlerDataIgnoreHandle(void *p1, const void *hd, const char *p2, return F(static_cast<P1>(p1), p2, p3); } -// Function that casts the handler data parameter. +/* Function that casts the handler data parameter. */ template <class R, class P1, class P2, R F(P1, P2)> R CastHandlerData2(void *c, const void *hd) { return F(static_cast<P1>(c), static_cast<P2>(hd)); @@ -5609,7 +4748,7 @@ R CastHandlerDataIgnoreHandle(void *c, const void *hd, const char *p3, return F(static_cast<P1>(c), static_cast<P2>(hd), p3, p4); } -// For unbound functions, ignore the handler data. +/* For unbound functions, ignore the handler data. */ template <class R, class P1, R F(P1), class I, class T> struct ConvertParams<Func1<R, P1, F, I>, T> { typedef Func2<R, void *, const void *, IgnoreHandlerData2<R, P1, F>, I> Func; @@ -5623,8 +4762,8 @@ struct ConvertParams<Func2<R, P1, P2, F, I>, IgnoreHandlerData3<R, P1, P3_2, P2, F>, I> Func; }; -// For StringBuffer only; this ignores both the handler data and the -// BufferHandle. +/* For StringBuffer only; this ignores both the handler data and the + * BufferHandle. */ template <class R, class P1, R F(P1, const char *, size_t), class I, class T> struct ConvertParams<Func3<R, P1, const char *, size_t, F, I>, T> { typedef Func5<R, void *, const void *, const char *, size_t, @@ -5639,7 +4778,7 @@ struct ConvertParams<Func4<R, P1, P2, P3, P4, F, I>, T> { IgnoreHandlerData5<R, P1, P2, P3, P4, F>, I> Func; }; -// For bound functions, cast the handler data. +/* For bound functions, cast the handler data. */ template <class R, class P1, class P2, R F(P1, P2), class I, class T> struct ConvertParams<BoundFunc2<R, P1, P2, F, I>, T> { typedef Func2<R, void *, const void *, CastHandlerData2<R, P1, P2, F>, I> @@ -5654,7 +4793,7 @@ struct ConvertParams<BoundFunc3<R, P1, P2, P3, F, I>, CastHandlerData3<R, P1, P2, P3_2, P3, F>, I> Func; }; -// For StringBuffer only; this ignores the BufferHandle. +/* For StringBuffer only; this ignores the BufferHandle. */ template <class R, class P1, class P2, R F(P1, P2, const char *, size_t), class I, class T> struct ConvertParams<BoundFunc4<R, P1, P2, const char *, size_t, F, I>, T> { @@ -5670,8 +4809,8 @@ struct ConvertParams<BoundFunc5<R, P1, P2, P3, P4, P5, F, I>, T> { CastHandlerData5<R, P1, P2, P3, P4, P5, F>, I> Func; }; -// utype/ltype are upper/lower-case, ctype is canonical C type, vtype is -// variant C type. +/* utype/ltype are upper/lower-case, ctype is canonical C type, vtype is + * variant C type. */ #define TYPE_METHODS(utype, ltype, ctype, vtype) \ template <> struct CanonicalType<vtype> { \ typedef ctype Type; \ @@ -5686,22 +4825,22 @@ struct ConvertParams<BoundFunc5<R, P1, P2, P3, P4, P5, F, I>, T> { return upb_handlers_set##ltype(this, f, handler.handler_, &handler.attr_); \ } \ -TYPE_METHODS(Double, double, double, double); -TYPE_METHODS(Float, float, float, float); -TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64_T); -TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32_T); -TYPE_METHODS(Int64, int64, int64_t, UPB_INT64_T); -TYPE_METHODS(Int32, int32, int32_t, UPB_INT32_T); -TYPE_METHODS(Bool, bool, bool, bool); +TYPE_METHODS(Double, double, double, double) +TYPE_METHODS(Float, float, float, float) +TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64_T) +TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32_T) +TYPE_METHODS(Int64, int64, int64_t, UPB_INT64_T) +TYPE_METHODS(Int32, int32, int32_t, UPB_INT32_T) +TYPE_METHODS(Bool, bool, bool, bool) #ifdef UPB_TWO_32BIT_TYPES -TYPE_METHODS(Int32, int32, int32_t, UPB_INT32ALT_T); -TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32ALT_T); +TYPE_METHODS(Int32, int32, int32_t, UPB_INT32ALT_T) +TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32ALT_T) #endif #ifdef UPB_TWO_64BIT_TYPES -TYPE_METHODS(Int64, int64, int64_t, UPB_INT64ALT_T); -TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64ALT_T); +TYPE_METHODS(Int64, int64, int64_t, UPB_INT64ALT_T) +TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64ALT_T) #endif #undef TYPE_METHODS @@ -5709,7 +4848,8 @@ template <> struct CanonicalType<Status*> { typedef Status* Type; }; -// Type methods that are only one-per-canonical-type and not one-per-cvariant. +/* Type methods that are only one-per-canonical-type and not + * one-per-cvariant. */ #define TYPE_METHODS(utype, ctype) \ inline bool Handlers::Set##utype##Handler(const FieldDef *f, \ @@ -5717,13 +4857,13 @@ template <> struct CanonicalType<Status*> { return SetValueHandler<ctype>(f, h); \ } \ -TYPE_METHODS(Double, double); -TYPE_METHODS(Float, float); -TYPE_METHODS(UInt64, uint64_t); -TYPE_METHODS(UInt32, uint32_t); -TYPE_METHODS(Int64, int64_t); -TYPE_METHODS(Int32, int32_t); -TYPE_METHODS(Bool, bool); +TYPE_METHODS(Double, double) +TYPE_METHODS(Float, float) +TYPE_METHODS(UInt64, uint64_t) +TYPE_METHODS(UInt32, uint32_t) +TYPE_METHODS(Int64, int64_t) +TYPE_METHODS(Int32, int32_t) +TYPE_METHODS(Bool, bool) #undef TYPE_METHODS template <class F> struct ReturnOf; @@ -5766,23 +4906,23 @@ inline Handler<T>::Handler(F func) ReturnWrappedFunc; handler_ = ReturnWrappedFunc().Call; - // Set attributes based on what templates can statically tell us about the - // user's function. + /* Set attributes based on what templates can statically tell us about the + * user's function. */ - // If the original function returns void, then we know that we wrapped it to - // always return ok. + /* If the original function returns void, then we know that we wrapped it to + * always return ok. */ bool always_ok = is_same<typename F::FuncInfo::Return, void>::value; attr_.SetAlwaysOk(always_ok); - // Closure parameter and return type. + /* Closure parameter and return type. */ attr_.SetClosureType(UniquePtrForType<typename F::FuncInfo::Closure>()); - // We use the closure type (from the first parameter) if the return type is - // void or bool, since these are the two cases we wrap to return the closure's - // type anyway. - // - // This is all nonsense for non START* handlers, but it doesn't matter because - // in that case the value will be ignored. + /* We use the closure type (from the first parameter) if the return type is + * void or bool, since these are the two cases we wrap to return the closure's + * type anyway. + * + * This is all nonsense for non START* handlers, but it doesn't matter because + * in that case the value will be ignored. */ typedef typename FirstUnlessVoidOrBool<typename F::FuncInfo::Return, typename F::FuncInfo::Closure>::value EffectiveReturn; @@ -5853,19 +4993,6 @@ inline reffed_ptr<const Handlers> Handlers::NewFrozen( const upb_handlers *h = upb_handlers_newfrozen(m, &h, callback, closure); return reffed_ptr<const Handlers>(h, &h); } -inline bool Handlers::IsFrozen() const { return upb_handlers_isfrozen(this); } -inline void Handlers::Ref(const void *owner) const { - upb_handlers_ref(this, owner); -} -inline void Handlers::Unref(const void *owner) const { - upb_handlers_unref(this, owner); -} -inline void Handlers::DonateRef(const void *from, const void *to) const { - upb_handlers_donateref(this, from, to); -} -inline void Handlers::CheckRef(const void *owner) const { - upb_handlers_checkref(this, owner); -} inline const Status* Handlers::status() { return upb_handlers_status(this); } @@ -5981,9 +5108,9 @@ inline BytesHandler::BytesHandler() { inline BytesHandler::~BytesHandler() {} -} // namespace upb +} /* namespace upb */ -#endif // __cplusplus +#endif /* __cplusplus */ #undef UPB_TWO_32BIT_TYPES @@ -5997,9 +5124,9 @@ inline BytesHandler::~BytesHandler() {} #undef UPB_INT64ALT_T #undef UPB_UINT64ALT_T -#endif // UPB_HANDLERS_INL_H_ +#endif /* UPB_HANDLERS_INL_H_ */ -#endif // UPB_HANDLERS_H +#endif /* UPB_HANDLERS_H */ /* * upb - a minimalist implementation of protocol buffers. * @@ -6028,32 +5155,34 @@ class SeededAllocator; } #endif -UPB_DECLARE_TYPE(upb::Environment, upb_env); -UPB_DECLARE_TYPE(upb::SeededAllocator, upb_seededalloc); +UPB_DECLARE_TYPE(upb::Environment, upb_env) +UPB_DECLARE_TYPE(upb::SeededAllocator, upb_seededalloc) typedef void *upb_alloc_func(void *ud, void *ptr, size_t oldsize, size_t size); typedef void upb_cleanup_func(void *ud); typedef bool upb_error_func(void *ud, const upb_status *status); -// An environment is *not* thread-safe. -UPB_DEFINE_CLASS0(upb::Environment, +#ifdef __cplusplus + +/* An environment is *not* thread-safe. */ +class upb::Environment { public: Environment(); ~Environment(); - // Set a custom memory allocation function for the environment. May ONLY - // be called before any calls to Malloc()/Realloc()/AddCleanup() below. - // If this is not called, the system realloc() function will be used. - // The given user pointer "ud" will be passed to the allocation function. - // - // The allocation function will not receive corresponding "free" calls. it - // must ensure that the memory is valid for the lifetime of the Environment, - // but it may be reclaimed any time thereafter. The likely usage is that - // "ud" points to a stateful allocator, and that the allocator frees all - // memory, arena-style, when it is destroyed. In this case the allocator must - // outlive the Environment. Another possibility is that the allocation - // function returns GC-able memory that is guaranteed to be GC-rooted for the - // life of the Environment. + /* Set a custom memory allocation function for the environment. May ONLY + * be called before any calls to Malloc()/Realloc()/AddCleanup() below. + * If this is not called, the system realloc() function will be used. + * The given user pointer "ud" will be passed to the allocation function. + * + * The allocation function will not receive corresponding "free" calls. it + * must ensure that the memory is valid for the lifetime of the Environment, + * but it may be reclaimed any time thereafter. The likely usage is that + * "ud" points to a stateful allocator, and that the allocator frees all + * memory, arena-style, when it is destroyed. In this case the allocator must + * outlive the Environment. Another possibility is that the allocation + * function returns GC-able memory that is guaranteed to be GC-rooted for the + * life of the Environment. */ void SetAllocationFunction(upb_alloc_func* alloc, void* ud); template<class T> @@ -6061,74 +5190,76 @@ UPB_DEFINE_CLASS0(upb::Environment, SetAllocationFunction(allocator->GetAllocationFunction(), allocator); } - // Set a custom error reporting function. + /* Set a custom error reporting function. */ void SetErrorFunction(upb_error_func* func, void* ud); - // Set the error reporting function to simply copy the status to the given - // status and abort. + /* Set the error reporting function to simply copy the status to the given + * status and abort. */ void ReportErrorsTo(Status* status); - // Returns true if all allocations and AddCleanup() calls have succeeded, - // and no errors were reported with ReportError() (except ones that recovered - // successfully). + /* Returns true if all allocations and AddCleanup() calls have succeeded, + * and no errors were reported with ReportError() (except ones that recovered + * successfully). */ bool ok() const; - ////////////////////////////////////////////////////////////////////////////// - // Functions for use by encoders/decoders. + /* Functions for use by encoders/decoders. **********************************/ - // Reports an error to this environment's callback, returning true if - // the caller should try to recover. + /* Reports an error to this environment's callback, returning true if + * the caller should try to recover. */ bool ReportError(const Status* status); - // Allocate memory. Uses the environment's allocation function. - // - // There is no need to free(). All memory will be freed automatically, but is - // guaranteed to outlive the Environment. + /* Allocate memory. Uses the environment's allocation function. + * + * There is no need to free(). All memory will be freed automatically, but is + * guaranteed to outlive the Environment. */ void* Malloc(size_t size); - // Reallocate memory. Preserves "oldsize" bytes from the existing buffer - // Requires: oldsize <= existing_size. - // - // TODO(haberman): should we also enforce that oldsize <= size? + /* Reallocate memory. Preserves "oldsize" bytes from the existing buffer + * Requires: oldsize <= existing_size. + * + * TODO(haberman): should we also enforce that oldsize <= size? */ void* Realloc(void* ptr, size_t oldsize, size_t size); - // Add a cleanup function to run when the environment is destroyed. - // Returns false on out-of-memory. - // - // The first call to AddCleanup() after SetAllocationFunction() is guaranteed - // to return true -- this makes it possible to robustly set a cleanup handler - // for a custom allocation function. + /* Add a cleanup function to run when the environment is destroyed. + * Returns false on out-of-memory. + * + * The first call to AddCleanup() after SetAllocationFunction() is guaranteed + * to return true -- this makes it possible to robustly set a cleanup handler + * for a custom allocation function. */ bool AddCleanup(upb_cleanup_func* func, void* ud); - // Total number of bytes that have been allocated. It is undefined what - // Realloc() does to this counter. + /* Total number of bytes that have been allocated. It is undefined what + * Realloc() does to this counter. */ size_t BytesAllocated() const; private: - UPB_DISALLOW_COPY_AND_ASSIGN(Environment); -, -UPB_DEFINE_STRUCT0(upb_env, + UPB_DISALLOW_COPY_AND_ASSIGN(Environment) + +#else +struct upb_env { +#endif /* __cplusplus */ + bool ok_; size_t bytes_allocated; - // Alloc function. + /* Alloc function. */ upb_alloc_func *alloc; void *alloc_ud; - // Error-reporting function. + /* Error-reporting function. */ upb_error_func *err; void *err_ud; - // Userdata for default alloc func. + /* Userdata for default alloc func. */ void *default_alloc_ud; - // Cleanup entries. Pointer to a cleanup_ent, defined in env.c + /* Cleanup entries. Pointer to a cleanup_ent, defined in env.c */ void *cleanup_head; - // For future expansion, since the size of this struct is exposed to users. + /* For future expansion, since the size of this struct is exposed to users. */ void *future1; void *future2; -)); +}; UPB_BEGIN_EXTERN_C @@ -6146,46 +5277,51 @@ size_t upb_env_bytesallocated(const upb_env *e); UPB_END_EXTERN_C -// An allocator that allocates from an initial memory region (likely the stack) -// before falling back to another allocator. -UPB_DEFINE_CLASS0(upb::SeededAllocator, +#ifdef __cplusplus + +/* An allocator that allocates from an initial memory region (likely the stack) + * before falling back to another allocator. */ +class upb::SeededAllocator { public: SeededAllocator(void *mem, size_t len); ~SeededAllocator(); - // Set a custom fallback memory allocation function for the allocator, to use - // once the initial region runs out. - // - // May ONLY be called before GetAllocationFunction(). If this is not - // called, the system realloc() will be the fallback allocator. + /* Set a custom fallback memory allocation function for the allocator, to use + * once the initial region runs out. + * + * May ONLY be called before GetAllocationFunction(). If this is not + * called, the system realloc() will be the fallback allocator. */ void SetFallbackAllocator(upb_alloc_func *alloc, void *ud); - // Gets the allocation function for this allocator. + /* Gets the allocation function for this allocator. */ upb_alloc_func* GetAllocationFunction(); private: - UPB_DISALLOW_COPY_AND_ASSIGN(SeededAllocator); -, -UPB_DEFINE_STRUCT0(upb_seededalloc, - // Fallback alloc function. + UPB_DISALLOW_COPY_AND_ASSIGN(SeededAllocator) + +#else +struct upb_seededalloc { +#endif /* __cplusplus */ + + /* Fallback alloc function. */ upb_alloc_func *alloc; upb_cleanup_func *alloc_cleanup; void *alloc_ud; bool need_cleanup; bool returned_allocfunc; - // Userdata for default alloc func. + /* Userdata for default alloc func. */ void *default_alloc_ud; - // Pointers for the initial memory region. + /* Pointers for the initial memory region. */ char *mem_base; char *mem_ptr; char *mem_limit; - // For future expansion, since the size of this struct is exposed to users. + /* For future expansion, since the size of this struct is exposed to users. */ void *future1; void *future2; -)); +}; UPB_BEGIN_EXTERN_C @@ -6250,11 +5386,11 @@ inline upb_alloc_func *SeededAllocator::GetAllocationFunction() { return upb_seededalloc_getallocfunc(this); } -} // namespace upb +} /* namespace upb */ -#endif // __cplusplus +#endif /* __cplusplus */ -#endif // UPB_ENV_H_ +#endif /* UPB_ENV_H_ */ /* * upb - a minimalist implementation of protocol buffers. * @@ -6286,88 +5422,90 @@ class Sink; } #endif -UPB_DECLARE_TYPE(upb::BufferSource, upb_bufsrc); -UPB_DECLARE_TYPE(upb::BytesSink, upb_bytessink); -UPB_DECLARE_TYPE(upb::Sink, upb_sink); - -// A upb::Sink is an object that binds a upb::Handlers object to some runtime -// state. It represents an endpoint to which data can be sent. -// -// TODO(haberman): right now all of these functions take selectors. Should they -// take selectorbase instead? -// -// ie. instead of calling: -// sink->StartString(FOO_FIELD_START_STRING, ...) -// a selector base would let you say: -// sink->StartString(FOO_FIELD, ...) -// -// This would make call sites a little nicer and require emitting fewer selector -// definitions in .h files. -// -// But the current scheme has the benefit that you can retrieve a function -// pointer for any handler with handlers->GetHandler(selector), without having -// to have a separate GetHandler() function for each handler type. The JIT -// compiler uses this. To accommodate we'd have to expose a separate -// GetHandler() for every handler type. -// -// Also to ponder: selectors right now are independent of a specific Handlers -// instance. In other words, they allocate a number to every possible handler -// that *could* be registered, without knowing anything about what handlers -// *are* registered. That means that using selectors as table offsets prohibits -// us from compacting the handler table at Freeze() time. If the table is very -// sparse, this could be wasteful. -// -// Having another selector-like thing that is specific to a Handlers instance -// would allow this compacting, but then it would be impossible to write code -// ahead-of-time that can be bound to any Handlers instance at runtime. For -// example, a .proto file parser written as straight C will not know what -// Handlers it will be bound to, so when it calls sink->StartString() what -// selector will it pass? It needs a selector like we have today, that is -// independent of any particular upb::Handlers. -// -// Is there a way then to allow Handlers table compaction? -UPB_DEFINE_CLASS0(upb::Sink, +UPB_DECLARE_TYPE(upb::BufferSource, upb_bufsrc) +UPB_DECLARE_TYPE(upb::BytesSink, upb_bytessink) +UPB_DECLARE_TYPE(upb::Sink, upb_sink) + +#ifdef __cplusplus + +/* A upb::Sink is an object that binds a upb::Handlers object to some runtime + * state. It represents an endpoint to which data can be sent. + * + * TODO(haberman): right now all of these functions take selectors. Should they + * take selectorbase instead? + * + * ie. instead of calling: + * sink->StartString(FOO_FIELD_START_STRING, ...) + * a selector base would let you say: + * sink->StartString(FOO_FIELD, ...) + * + * This would make call sites a little nicer and require emitting fewer selector + * definitions in .h files. + * + * But the current scheme has the benefit that you can retrieve a function + * pointer for any handler with handlers->GetHandler(selector), without having + * to have a separate GetHandler() function for each handler type. The JIT + * compiler uses this. To accommodate we'd have to expose a separate + * GetHandler() for every handler type. + * + * Also to ponder: selectors right now are independent of a specific Handlers + * instance. In other words, they allocate a number to every possible handler + * that *could* be registered, without knowing anything about what handlers + * *are* registered. That means that using selectors as table offsets prohibits + * us from compacting the handler table at Freeze() time. If the table is very + * sparse, this could be wasteful. + * + * Having another selector-like thing that is specific to a Handlers instance + * would allow this compacting, but then it would be impossible to write code + * ahead-of-time that can be bound to any Handlers instance at runtime. For + * example, a .proto file parser written as straight C will not know what + * Handlers it will be bound to, so when it calls sink->StartString() what + * selector will it pass? It needs a selector like we have today, that is + * independent of any particular upb::Handlers. + * + * Is there a way then to allow Handlers table compaction? */ +class upb::Sink { public: - // Constructor with no initialization; must be Reset() before use. + /* Constructor with no initialization; must be Reset() before use. */ Sink() {} - // Constructs a new sink for the given frozen handlers and closure. - // - // TODO: once the Handlers know the expected closure type, verify that T - // matches it. + /* Constructs a new sink for the given frozen handlers and closure. + * + * TODO: once the Handlers know the expected closure type, verify that T + * matches it. */ template <class T> Sink(const Handlers* handlers, T* closure); - // Resets the value of the sink. + /* Resets the value of the sink. */ template <class T> void Reset(const Handlers* handlers, T* closure); - // Returns the top-level object that is bound to this sink. - // - // TODO: once the Handlers know the expected closure type, verify that T - // matches it. + /* Returns the top-level object that is bound to this sink. + * + * TODO: once the Handlers know the expected closure type, verify that T + * matches it. */ template <class T> T* GetObject() const; - // Functions for pushing data into the sink. - // - // These return false if processing should stop (either due to error or just - // to suspend). - // - // These may not be called from within one of the same sink's handlers (in - // other words, handlers are not re-entrant). - - // Should be called at the start and end of every message; both the top-level - // message and submessages. This means that submessages should use the - // following sequence: - // sink->StartSubMessage(startsubmsg_selector); - // sink->StartMessage(); - // // ... - // sink->EndMessage(&status); - // sink->EndSubMessage(endsubmsg_selector); + /* Functions for pushing data into the sink. + * + * These return false if processing should stop (either due to error or just + * to suspend). + * + * These may not be called from within one of the same sink's handlers (in + * other words, handlers are not re-entrant). */ + + /* Should be called at the start and end of every message; both the top-level + * message and submessages. This means that submessages should use the + * following sequence: + * sink->StartSubMessage(startsubmsg_selector); + * sink->StartMessage(); + * // ... + * sink->EndMessage(&status); + * sink->EndSubMessage(endsubmsg_selector); */ bool StartMessage(); bool EndMessage(Status* status); - // Putting of individual values. These work for both repeated and - // non-repeated fields, but for repeated fields you must wrap them in - // calls to StartSequence()/EndSequence(). + /* Putting of individual values. These work for both repeated and + * non-repeated fields, but for repeated fields you must wrap them in + * calls to StartSequence()/EndSequence(). */ bool PutInt32(Handlers::Selector s, int32_t val); bool PutInt64(Handlers::Selector s, int64_t val); bool PutUInt32(Handlers::Selector s, uint32_t val); @@ -6376,92 +5514,101 @@ UPB_DEFINE_CLASS0(upb::Sink, bool PutDouble(Handlers::Selector s, double val); bool PutBool(Handlers::Selector s, bool val); - // Putting of string/bytes values. Each string can consist of zero or more - // non-contiguous buffers of data. - // - // For StartString(), the function will write a sink for the string to "sub." - // The sub-sink must be used for any/all PutStringBuffer() calls. + /* Putting of string/bytes values. Each string can consist of zero or more + * non-contiguous buffers of data. + * + * For StartString(), the function will write a sink for the string to "sub." + * The sub-sink must be used for any/all PutStringBuffer() calls. */ bool StartString(Handlers::Selector s, size_t size_hint, Sink* sub); size_t PutStringBuffer(Handlers::Selector s, const char *buf, size_t len, const BufferHandle *handle); bool EndString(Handlers::Selector s); - // For submessage fields. - // - // For StartSubMessage(), the function will write a sink for the string to - // "sub." The sub-sink must be used for any/all handlers called within the - // submessage. + /* For submessage fields. + * + * For StartSubMessage(), the function will write a sink for the string to + * "sub." The sub-sink must be used for any/all handlers called within the + * submessage. */ bool StartSubMessage(Handlers::Selector s, Sink* sub); bool EndSubMessage(Handlers::Selector s); - // For repeated fields of any type, the sequence of values must be wrapped in - // these calls. - // - // For StartSequence(), the function will write a sink for the string to - // "sub." The sub-sink must be used for any/all handlers called within the - // sequence. + /* For repeated fields of any type, the sequence of values must be wrapped in + * these calls. + * + * For StartSequence(), the function will write a sink for the string to + * "sub." The sub-sink must be used for any/all handlers called within the + * sequence. */ bool StartSequence(Handlers::Selector s, Sink* sub); bool EndSequence(Handlers::Selector s); - // Copy and assign specifically allowed. - // We don't even bother making these members private because so many - // functions need them and this is mainly just a dumb data container anyway. -, -UPB_DEFINE_STRUCT0(upb_sink, + /* Copy and assign specifically allowed. + * We don't even bother making these members private because so many + * functions need them and this is mainly just a dumb data container anyway. + */ +#else +struct upb_sink { +#endif const upb_handlers *handlers; void *closure; -)); +}; -UPB_DEFINE_CLASS0(upb::BytesSink, +#ifdef __cplusplus +class upb::BytesSink { public: BytesSink() {} - // Constructs a new sink for the given frozen handlers and closure. - // - // TODO(haberman): once the Handlers know the expected closure type, verify - // that T matches it. + /* Constructs a new sink for the given frozen handlers and closure. + * + * TODO(haberman): once the Handlers know the expected closure type, verify + * that T matches it. */ template <class T> BytesSink(const BytesHandler* handler, T* closure); - // Resets the value of the sink. + /* Resets the value of the sink. */ template <class T> void Reset(const BytesHandler* handler, T* closure); bool Start(size_t size_hint, void **subc); size_t PutBuffer(void *subc, const char *buf, size_t len, const BufferHandle *handle); bool End(); -, -UPB_DEFINE_STRUCT0(upb_bytessink, +#else +struct upb_bytessink { +#endif const upb_byteshandler *handler; void *closure; -)); +}; + +#ifdef __cplusplus -// A class for pushing a flat buffer of data to a BytesSink. -// You can construct an instance of this to get a resumable source, -// or just call the static PutBuffer() to do a non-resumable push all in one go. -UPB_DEFINE_CLASS0(upb::BufferSource, +/* A class for pushing a flat buffer of data to a BytesSink. + * You can construct an instance of this to get a resumable source, + * or just call the static PutBuffer() to do a non-resumable push all in one + * go. */ +class upb::BufferSource { public: BufferSource(); BufferSource(const char* buf, size_t len, BytesSink* sink); - // Returns true if the entire buffer was pushed successfully. Otherwise the - // next call to PutNext() will resume where the previous one left off. - // TODO(haberman): implement this. + /* Returns true if the entire buffer was pushed successfully. Otherwise the + * next call to PutNext() will resume where the previous one left off. + * TODO(haberman): implement this. */ bool PutNext(); - // A static version; with this version is it not possible to resume in the - // case of failure or a partially-consumed buffer. + /* A static version; with this version is it not possible to resume in the + * case of failure or a partially-consumed buffer. */ static bool PutBuffer(const char* buf, size_t len, BytesSink* sink); template <class T> static bool PutBuffer(const T& str, BytesSink* sink) { return PutBuffer(str.c_str(), str.size(), sink); } -, -UPB_DEFINE_STRUCT0(upb_bufsrc, -)); +#else +struct upb_bufsrc { + char dummy; +#endif +}; -UPB_BEGIN_EXTERN_C // { +UPB_BEGIN_EXTERN_C -// Inline definitions. +/* Inline definitions. */ UPB_INLINE void upb_bytessink_reset(upb_bytessink *s, const upb_byteshandler *h, void *closure) { @@ -6471,10 +5618,11 @@ UPB_INLINE void upb_bytessink_reset(upb_bytessink *s, const upb_byteshandler *h, UPB_INLINE bool upb_bytessink_start(upb_bytessink *s, size_t size_hint, void **subc) { + typedef upb_startstr_handlerfunc func; + func *start; *subc = s->closure; if (!s->handler) return true; - upb_startstr_handlerfunc *start = - (upb_startstr_handlerfunc *)s->handler->table[UPB_STARTSTR_SELECTOR].func; + start = (func *)s->handler->table[UPB_STARTSTR_SELECTOR].func; if (!start) return true; *subc = start(s->closure, upb_handlerattr_handlerdata( @@ -6486,9 +5634,10 @@ UPB_INLINE bool upb_bytessink_start(upb_bytessink *s, size_t size_hint, UPB_INLINE size_t upb_bytessink_putbuf(upb_bytessink *s, void *subc, const char *buf, size_t size, const upb_bufhandle* handle) { + typedef upb_string_handlerfunc func; + func *putbuf; if (!s->handler) return true; - upb_string_handlerfunc *putbuf = - (upb_string_handlerfunc *)s->handler->table[UPB_STRING_SELECTOR].func; + putbuf = (func *)s->handler->table[UPB_STRING_SELECTOR].func; if (!putbuf) return true; return putbuf(subc, upb_handlerattr_handlerdata( @@ -6497,9 +5646,10 @@ UPB_INLINE size_t upb_bytessink_putbuf(upb_bytessink *s, void *subc, } UPB_INLINE bool upb_bytessink_end(upb_bytessink *s) { + typedef upb_endfield_handlerfunc func; + func *end; if (!s->handler) return true; - upb_endfield_handlerfunc *end = - (upb_endfield_handlerfunc *)s->handler->table[UPB_ENDSTR_SELECTOR].func; + end = (func *)s->handler->table[UPB_ENDSTR_SELECTOR].func; if (!end) return true; return end(s->closure, @@ -6510,10 +5660,11 @@ UPB_INLINE bool upb_bytessink_end(upb_bytessink *s) { UPB_INLINE bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink *sink) { void *subc; + bool ret; upb_bufhandle handle; upb_bufhandle_init(&handle); upb_bufhandle_setbuf(&handle, buf, 0); - bool ret = upb_bytessink_start(sink, len, &subc); + ret = upb_bytessink_start(sink, len, &subc); if (ret && len != 0) { ret = (upb_bytessink_putbuf(sink, subc, buf, len, &handle) == len); } @@ -6527,21 +5678,23 @@ UPB_INLINE bool upb_bufsrc_putbuf(const char *buf, size_t len, #define PUTVAL(type, ctype) \ UPB_INLINE bool upb_sink_put##type(upb_sink *s, upb_selector_t sel, \ ctype val) { \ + typedef upb_##type##_handlerfunc functype; \ + functype *func; \ + const void *hd; \ if (!s->handlers) return true; \ - upb_##type##_handlerfunc *func = \ - (upb_##type##_handlerfunc *)upb_handlers_gethandler(s->handlers, sel); \ + func = (functype *)upb_handlers_gethandler(s->handlers, sel); \ if (!func) return true; \ - const void *hd = upb_handlers_gethandlerdata(s->handlers, sel); \ + hd = upb_handlers_gethandlerdata(s->handlers, sel); \ return func(s->closure, hd, val); \ } -PUTVAL(int32, int32_t); -PUTVAL(int64, int64_t); -PUTVAL(uint32, uint32_t); -PUTVAL(uint64, uint64_t); -PUTVAL(float, float); -PUTVAL(double, double); -PUTVAL(bool, bool); +PUTVAL(int32, int32_t) +PUTVAL(int64, int64_t) +PUTVAL(uint32, uint32_t) +PUTVAL(uint64, uint64_t) +PUTVAL(float, float) +PUTVAL(double, double) +PUTVAL(bool, bool) #undef PUTVAL UPB_INLINE void upb_sink_reset(upb_sink *s, const upb_handlers *h, void *c) { @@ -6552,114 +5705,129 @@ UPB_INLINE void upb_sink_reset(upb_sink *s, const upb_handlers *h, void *c) { UPB_INLINE size_t upb_sink_putstring(upb_sink *s, upb_selector_t sel, const char *buf, size_t n, const upb_bufhandle *handle) { + typedef upb_string_handlerfunc func; + func *handler; + const void *hd; if (!s->handlers) return n; - upb_string_handlerfunc *handler = - (upb_string_handlerfunc *)upb_handlers_gethandler(s->handlers, sel); + handler = (func *)upb_handlers_gethandler(s->handlers, sel); if (!handler) return n; - const void *hd = upb_handlers_gethandlerdata(s->handlers, sel); + hd = upb_handlers_gethandlerdata(s->handlers, sel); return handler(s->closure, hd, buf, n, handle); } UPB_INLINE bool upb_sink_startmsg(upb_sink *s) { + typedef upb_startmsg_handlerfunc func; + func *startmsg; + const void *hd; if (!s->handlers) return true; - upb_startmsg_handlerfunc *startmsg = - (upb_startmsg_handlerfunc *)upb_handlers_gethandler(s->handlers, - UPB_STARTMSG_SELECTOR); + startmsg = (func*)upb_handlers_gethandler(s->handlers, UPB_STARTMSG_SELECTOR); + if (!startmsg) return true; - const void *hd = - upb_handlers_gethandlerdata(s->handlers, UPB_STARTMSG_SELECTOR); + hd = upb_handlers_gethandlerdata(s->handlers, UPB_STARTMSG_SELECTOR); return startmsg(s->closure, hd); } UPB_INLINE bool upb_sink_endmsg(upb_sink *s, upb_status *status) { + typedef upb_endmsg_handlerfunc func; + func *endmsg; + const void *hd; if (!s->handlers) return true; - upb_endmsg_handlerfunc *endmsg = - (upb_endmsg_handlerfunc *)upb_handlers_gethandler(s->handlers, - UPB_ENDMSG_SELECTOR); + endmsg = (func *)upb_handlers_gethandler(s->handlers, UPB_ENDMSG_SELECTOR); if (!endmsg) return true; - const void *hd = - upb_handlers_gethandlerdata(s->handlers, UPB_ENDMSG_SELECTOR); + hd = upb_handlers_gethandlerdata(s->handlers, UPB_ENDMSG_SELECTOR); return endmsg(s->closure, hd, status); } UPB_INLINE bool upb_sink_startseq(upb_sink *s, upb_selector_t sel, upb_sink *sub) { + typedef upb_startfield_handlerfunc func; + func *startseq; + const void *hd; sub->closure = s->closure; sub->handlers = s->handlers; if (!s->handlers) return true; - upb_startfield_handlerfunc *startseq = - (upb_startfield_handlerfunc*)upb_handlers_gethandler(s->handlers, sel); + startseq = (func*)upb_handlers_gethandler(s->handlers, sel); if (!startseq) return true; - const void *hd = upb_handlers_gethandlerdata(s->handlers, sel); + hd = upb_handlers_gethandlerdata(s->handlers, sel); sub->closure = startseq(s->closure, hd); return sub->closure ? true : false; } UPB_INLINE bool upb_sink_endseq(upb_sink *s, upb_selector_t sel) { + typedef upb_endfield_handlerfunc func; + func *endseq; + const void *hd; if (!s->handlers) return true; - upb_endfield_handlerfunc *endseq = - (upb_endfield_handlerfunc*)upb_handlers_gethandler(s->handlers, sel); + endseq = (func*)upb_handlers_gethandler(s->handlers, sel); if (!endseq) return true; - const void *hd = upb_handlers_gethandlerdata(s->handlers, sel); + hd = upb_handlers_gethandlerdata(s->handlers, sel); return endseq(s->closure, hd); } UPB_INLINE bool upb_sink_startstr(upb_sink *s, upb_selector_t sel, size_t size_hint, upb_sink *sub) { + typedef upb_startstr_handlerfunc func; + func *startstr; + const void *hd; sub->closure = s->closure; sub->handlers = s->handlers; if (!s->handlers) return true; - upb_startstr_handlerfunc *startstr = - (upb_startstr_handlerfunc*)upb_handlers_gethandler(s->handlers, sel); + startstr = (func*)upb_handlers_gethandler(s->handlers, sel); if (!startstr) return true; - const void *hd = upb_handlers_gethandlerdata(s->handlers, sel); + hd = upb_handlers_gethandlerdata(s->handlers, sel); sub->closure = startstr(s->closure, hd, size_hint); return sub->closure ? true : false; } UPB_INLINE bool upb_sink_endstr(upb_sink *s, upb_selector_t sel) { + typedef upb_endfield_handlerfunc func; + func *endstr; + const void *hd; if (!s->handlers) return true; - upb_endfield_handlerfunc *endstr = - (upb_endfield_handlerfunc*)upb_handlers_gethandler(s->handlers, sel); + endstr = (func*)upb_handlers_gethandler(s->handlers, sel); if (!endstr) return true; - const void *hd = upb_handlers_gethandlerdata(s->handlers, sel); + hd = upb_handlers_gethandlerdata(s->handlers, sel); return endstr(s->closure, hd); } UPB_INLINE bool upb_sink_startsubmsg(upb_sink *s, upb_selector_t sel, upb_sink *sub) { + typedef upb_startfield_handlerfunc func; + func *startsubmsg; + const void *hd; sub->closure = s->closure; if (!s->handlers) { sub->handlers = NULL; return true; } sub->handlers = upb_handlers_getsubhandlers_sel(s->handlers, sel); - upb_startfield_handlerfunc *startsubmsg = - (upb_startfield_handlerfunc*)upb_handlers_gethandler(s->handlers, sel); + startsubmsg = (func*)upb_handlers_gethandler(s->handlers, sel); if (!startsubmsg) return true; - const void *hd = upb_handlers_gethandlerdata(s->handlers, sel); + hd = upb_handlers_gethandlerdata(s->handlers, sel); sub->closure = startsubmsg(s->closure, hd); return sub->closure ? true : false; } UPB_INLINE bool upb_sink_endsubmsg(upb_sink *s, upb_selector_t sel) { + typedef upb_endfield_handlerfunc func; + func *endsubmsg; + const void *hd; if (!s->handlers) return true; - upb_endfield_handlerfunc *endsubmsg = - (upb_endfield_handlerfunc*)upb_handlers_gethandler(s->handlers, sel); + endsubmsg = (func*)upb_handlers_gethandler(s->handlers, sel); if (!endsubmsg) return s->closure; - const void *hd = upb_handlers_gethandlerdata(s->handlers, sel); + hd = upb_handlers_gethandlerdata(s->handlers, sel); return endsubmsg(s->closure, hd); } -UPB_END_EXTERN_C // } +UPB_END_EXTERN_C #ifdef __cplusplus @@ -6748,7 +5916,7 @@ inline bool BufferSource::PutBuffer(const char *buf, size_t len, return upb_bufsrc_putbuf(buf, len, sink); } -} // namespace upb +} /* namespace upb */ #endif #endif @@ -6785,33 +5953,33 @@ namespace upb { struct Shim { typedef upb_shim_data Data; - // Sets a handler for the given field that writes the value to the given - // offset and, if hasbit >= 0, sets a bit at the given bit offset. Returns - // true if the handler was set successfully. + /* Sets a handler for the given field that writes the value to the given + * offset and, if hasbit >= 0, sets a bit at the given bit offset. Returns + * true if the handler was set successfully. */ static bool Set(Handlers *h, const FieldDef *f, size_t ofs, int32_t hasbit); - // If this handler is a shim, returns the corresponding upb::Shim::Data and - // stores the type in "type". Otherwise returns NULL. + /* If this handler is a shim, returns the corresponding upb::Shim::Data and + * stores the type in "type". Otherwise returns NULL. */ static const Data* GetData(const Handlers* h, Handlers::Selector s, FieldDef::Type* type); }; -} // namespace upb +} /* namespace upb */ #endif -UPB_BEGIN_EXTERN_C // { +UPB_BEGIN_EXTERN_C -// C API. +/* C API. */ bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset, int32_t hasbit); const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s, upb_fieldtype_t *type); -UPB_END_EXTERN_C // } +UPB_END_EXTERN_C #ifdef __cplusplus -// C++ Wrappers. +/* C++ Wrappers. */ namespace upb { inline bool Shim::Set(Handlers* h, const FieldDef* f, size_t ofs, int32_t hasbit) { @@ -6821,10 +5989,198 @@ inline const Shim::Data* Shim::GetData(const Handlers* h, Handlers::Selector s, FieldDef::Type* type) { return upb_shim_getdata(h, s, type); } -} // namespace upb +} /* namespace upb */ +#endif + +#endif /* UPB_SHIM_H */ +/* + * upb - a minimalist implementation of protocol buffers. + * + * Copyright (c) 2009-2012 Google Inc. See LICENSE for details. + * Author: Josh Haberman <jhaberman@gmail.com> + * + * A symtab (symbol table) stores a name->def map of upb_defs. Clients could + * always create such tables themselves, but upb_symtab has logic for resolving + * symbolic references, and in particular, for keeping a whole set of consistent + * defs when replacing some subset of those defs. This logic is nontrivial. + * + * This is a mixed C/C++ interface that offers a full API to both languages. + * See the top-level README for more information. + */ + +#ifndef UPB_SYMTAB_H_ +#define UPB_SYMTAB_H_ + + +#ifdef __cplusplus +#include <vector> +namespace upb { class SymbolTable; } +#endif + +UPB_DECLARE_DERIVED_TYPE(upb::SymbolTable, upb::RefCounted, + upb_symtab, upb_refcounted) + +typedef struct { + UPB_PRIVATE_FOR_CPP + upb_strtable_iter iter; + upb_deftype_t type; +} upb_symtab_iter; + +#ifdef __cplusplus + +/* Non-const methods in upb::SymbolTable are NOT thread-safe. */ +class upb::SymbolTable { + public: + /* Returns a new symbol table with a single ref owned by "owner." + * Returns NULL if memory allocation failed. */ + static reffed_ptr<SymbolTable> New(); + + /* Include RefCounted base methods. */ + UPB_REFCOUNTED_CPPMETHODS + + /* For all lookup functions, the returned pointer is not owned by the + * caller; it may be invalidated by any non-const call or unref of the + * SymbolTable! To protect against this, take a ref if desired. */ + + /* Freezes the symbol table: prevents further modification of it. + * After the Freeze() operation is successful, the SymbolTable must only be + * accessed via a const pointer. + * + * Unlike with upb::MessageDef/upb::EnumDef/etc, freezing a SymbolTable is not + * a necessary step in using a SymbolTable. If you have no need for it to be + * immutable, there is no need to freeze it ever. However sometimes it is + * useful, and SymbolTables that are statically compiled into the binary are + * always frozen by nature. */ + void Freeze(); + + /* Resolves the given symbol using the rules described in descriptor.proto, + * namely: + * + * 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). + * + * If not found, returns NULL. */ + const Def* Resolve(const char* base, const char* sym) const; + + /* Finds an entry in the symbol table with this exact name. If not found, + * returns NULL. */ + const Def* Lookup(const char *sym) const; + const MessageDef* LookupMessage(const char *sym) const; + const EnumDef* LookupEnum(const char *sym) const; + + /* TODO: introduce a C++ iterator, but make it nice and templated so that if + * you ask for an iterator of MessageDef the iterated elements are strongly + * typed as MessageDef*. */ + + /* Adds the given mutable defs to the symtab, resolving all symbols + * (including enum default values) and finalizing the defs. Only one def per + * name may be in the list, but defs can replace existing defs in the symtab. + * All defs must have a name -- anonymous defs are not allowed. Anonymous + * defs can still be frozen by calling upb_def_freeze() directly. + * + * Any existing defs that can reach defs that are being replaced will + * themselves be replaced also, so that the resulting set of defs is fully + * consistent. + * + * This logic implemented in this method is a convenience; ultimately it + * calls some combination of upb_fielddef_setsubdef(), upb_def_dup(), and + * upb_freeze(), any of which the client could call themself. However, since + * the logic for doing so is nontrivial, we provide it here. + * + * The entire operation either succeeds or fails. If the operation fails, + * the symtab is unchanged, false is returned, and status indicates the + * error. The caller passes a ref on all defs to the symtab (even if the + * operation fails). + * + * TODO(haberman): currently failure will leave the symtab unchanged, but may + * leave the defs themselves partially resolved. Does this matter? If so we + * could do a prepass that ensures that all symbols are resolvable and bail + * if not, so we don't mutate anything until we know the operation will + * succeed. + * + * TODO(haberman): since the defs must be mutable, refining a frozen def + * requires making mutable copies of the entire tree. This is wasteful if + * only a few messages are changing. We may want to add a way of adding a + * tree of frozen defs to the symtab (perhaps an alternate constructor where + * you pass the root of the tree?) */ + bool Add(Def*const* defs, int n, void* ref_donor, upb_status* status); + + bool Add(const std::vector<Def*>& defs, void *owner, Status* status) { + return Add((Def*const*)&defs[0], defs.size(), owner, status); + } + + private: + UPB_DISALLOW_POD_OPS(SymbolTable, upb::SymbolTable) +}; + +#endif /* __cplusplus */ + +UPB_BEGIN_EXTERN_C + +/* Native C API. */ + +/* Include refcounted methods like upb_symtab_ref(). */ +UPB_REFCOUNTED_CMETHODS(upb_symtab, upb_symtab_upcast) + +upb_symtab *upb_symtab_new(const void *owner); +void upb_symtab_freeze(upb_symtab *s); +const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base, + const char *sym); +const upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym); +const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym); +const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym); +bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor, + upb_status *status); + +/* upb_symtab_iter i; + * for(upb_symtab_begin(&i, s, type); !upb_symtab_done(&i); + * upb_symtab_next(&i)) { + * const upb_def *def = upb_symtab_iter_def(&i); + * // ... + * } + * + * For C we don't have separate iterators for const and non-const. + * It is the caller's responsibility to cast the upb_fielddef* to + * const if the upb_msgdef* is const. */ +void upb_symtab_begin(upb_symtab_iter *iter, const upb_symtab *s, + upb_deftype_t type); +void upb_symtab_next(upb_symtab_iter *iter); +bool upb_symtab_done(const upb_symtab_iter *iter); +const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter); + +UPB_END_EXTERN_C + +#ifdef __cplusplus +/* C++ inline wrappers. */ +namespace upb { +inline reffed_ptr<SymbolTable> SymbolTable::New() { + upb_symtab *s = upb_symtab_new(&s); + return reffed_ptr<SymbolTable>(s, &s); +} + +inline void SymbolTable::Freeze() { + return upb_symtab_freeze(this); +} +inline const Def *SymbolTable::Resolve(const char *base, + const char *sym) const { + return upb_symtab_resolve(this, base, sym); +} +inline const Def* SymbolTable::Lookup(const char *sym) const { + return upb_symtab_lookup(this, sym); +} +inline const MessageDef *SymbolTable::LookupMessage(const char *sym) const { + return upb_symtab_lookupmsg(this, sym); +} +inline bool SymbolTable::Add( + Def*const* defs, int n, void* ref_donor, upb_status* status) { + return upb_symtab_add(this, (upb_def*const*)defs, n, ref_donor, status); +} +} /* namespace upb */ #endif -#endif // UPB_SHIM_H +#endif /* UPB_SYMTAB_H_ */ /* * upb - a minimalist implementation of protocol buffers. * @@ -6843,52 +6199,52 @@ inline const Shim::Data* Shim::GetData(const Handlers* h, Handlers::Selector s, namespace upb { namespace descriptor { class Reader; -} // namespace descriptor -} // namespace upb +} /* namespace descriptor */ +} /* namespace upb */ #endif -UPB_DECLARE_TYPE(upb::descriptor::Reader, upb_descreader); +UPB_DECLARE_TYPE(upb::descriptor::Reader, upb_descreader) #ifdef __cplusplus -// Class that receives descriptor data according to the descriptor.proto schema -// and use it to build upb::Defs corresponding to that schema. +/* Class that receives descriptor data according to the descriptor.proto schema + * and use it to build upb::Defs corresponding to that schema. */ class upb::descriptor::Reader { public: - // These handlers must have come from NewHandlers() and must outlive the - // Reader. - // - // TODO: generate the handlers statically (like we do with the - // descriptor.proto defs) so that there is no need to pass this parameter (or - // to build/memory-manage the handlers at runtime at all). Unfortunately this - // is a bit tricky to implement for Handlers, but necessary to simplify this - // interface. + /* These handlers must have come from NewHandlers() and must outlive the + * Reader. + * + * TODO: generate the handlers statically (like we do with the + * descriptor.proto defs) so that there is no need to pass this parameter (or + * to build/memory-manage the handlers at runtime at all). Unfortunately this + * is a bit tricky to implement for Handlers, but necessary to simplify this + * interface. */ static Reader* Create(Environment* env, const Handlers* handlers); - // The reader's input; this is where descriptor.proto data should be sent. + /* The reader's input; this is where descriptor.proto data should be sent. */ Sink* input(); - // Returns an array of all defs that have been parsed, and transfers ownership - // of them to "owner". The number of defs is stored in *n. Ownership of the - // returned array is retained and is invalidated by any other call into - // Reader. - // - // These defs are not frozen or resolved; they are ready to be added to a - // symtab. + /* Returns an array of all defs that have been parsed, and transfers ownership + * of them to "owner". The number of defs is stored in *n. Ownership of the + * returned array is retained and is invalidated by any other call into + * Reader. + * + * These defs are not frozen or resolved; they are ready to be added to a + * symtab. */ upb::Def** GetDefs(void* owner, int* n); - // Builds and returns handlers for the reader, owned by "owner." + /* Builds and returns handlers for the reader, owned by "owner." */ static Handlers* NewHandlers(const void* owner); private: - UPB_DISALLOW_POD_OPS(Reader, upb::descriptor::Reader); + UPB_DISALLOW_POD_OPS(Reader, upb::descriptor::Reader) }; #endif UPB_BEGIN_EXTERN_C -// C API. +/* C API. */ upb_descreader *upb_descreader_create(upb_env *e, const upb_handlers *h); upb_sink *upb_descreader_input(upb_descreader *r); upb_def **upb_descreader_getdefs(upb_descreader *r, void *owner, int *n); @@ -6897,7 +6253,7 @@ const upb_handlers *upb_descreader_newhandlers(const void *owner); UPB_END_EXTERN_C #ifdef __cplusplus -// C++ implementation details. ///////////////////////////////////////////////// +/* C++ implementation details. ************************************************/ namespace upb { namespace descriptor { inline Reader* Reader::Create(Environment* e, const Handlers *h) { @@ -6907,11 +6263,809 @@ inline Sink* Reader::input() { return upb_descreader_input(this); } inline upb::Def** Reader::GetDefs(void* owner, int* n) { return upb_descreader_getdefs(this, owner, n); } -} // namespace descriptor -} // namespace upb +} /* namespace descriptor */ +} /* namespace upb */ #endif -#endif // UPB_DESCRIPTOR_H +#endif /* UPB_DESCRIPTOR_H */ +/* This file contains accessors for a set of compiled-in defs. + * Note that unlike Google's protobuf, it does *not* define + * generated classes or any other kind of data structure for + * actually storing protobufs. It only contains *defs* which + * let you reflect over a protobuf *schema*. + */ +/* This file was generated by upbc (the upb compiler). + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_ +#define GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_ + + +#ifdef __cplusplus +UPB_BEGIN_EXTERN_C +#endif + +/* Enums */ + +typedef enum { + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_OPTIONAL = 1, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REQUIRED = 2, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED = 3 +} google_protobuf_FieldDescriptorProto_Label; + +typedef enum { + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE = 1, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FLOAT = 2, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT64 = 3, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT64 = 4, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32 = 5, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED64 = 6, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED32 = 7, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BOOL = 8, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING = 9, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP = 10, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE = 11, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES = 12, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32 = 13, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ENUM = 14, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED32 = 15, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED64 = 16, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT32 = 17, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64 = 18 +} google_protobuf_FieldDescriptorProto_Type; + +typedef enum { + GOOGLE_PROTOBUF_FIELDOPTIONS_STRING = 0, + GOOGLE_PROTOBUF_FIELDOPTIONS_CORD = 1, + GOOGLE_PROTOBUF_FIELDOPTIONS_STRING_PIECE = 2 +} google_protobuf_FieldOptions_CType; + +typedef enum { + GOOGLE_PROTOBUF_FILEOPTIONS_SPEED = 1, + GOOGLE_PROTOBUF_FILEOPTIONS_CODE_SIZE = 2, + GOOGLE_PROTOBUF_FILEOPTIONS_LITE_RUNTIME = 3 +} google_protobuf_FileOptions_OptimizeMode; + +/* Selectors */ + +/* google.protobuf.DescriptorProto */ +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSUBMSG 2 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSUBMSG 3 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 4 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSUBMSG 5 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSUBMSG 6 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_STARTSUBMSG 7 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSEQ 8 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_ENDSEQ 9 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_ENDSUBMSG 10 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSEQ 11 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSEQ 12 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSUBMSG 13 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 14 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 15 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 16 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSEQ 17 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSEQ 18 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSUBMSG 19 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSEQ 20 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSEQ 21 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSUBMSG 22 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_ENDSUBMSG 23 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_STRING 24 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_STARTSTR 25 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_ENDSTR 26 + +/* google.protobuf.DescriptorProto.ExtensionRange */ +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START_INT32 2 +#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END_INT32 3 + +/* google.protobuf.EnumDescriptorProto */ +#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_STARTSUBMSG 2 +#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 3 +#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_STARTSEQ 4 +#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_ENDSEQ 5 +#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_ENDSUBMSG 6 +#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 7 +#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_STRING 8 +#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_STARTSTR 9 +#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_ENDSTR 10 + +/* google.protobuf.EnumOptions */ +#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 +#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 +#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 +#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 +#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_ALLOW_ALIAS_BOOL 6 + +/* google.protobuf.EnumValueDescriptorProto */ +#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 2 +#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 3 +#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_STRING 4 +#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_STARTSTR 5 +#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_ENDSTR 6 +#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER_INT32 7 + +/* google.protobuf.EnumValueOptions */ +#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 +#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 +#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 +#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 + +/* google.protobuf.FieldDescriptorProto */ +#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 2 +#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 3 +#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_STRING 4 +#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_STARTSTR 5 +#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_ENDSTR 6 +#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STRING 7 +#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STARTSTR 8 +#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_ENDSTR 9 +#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER_INT32 10 +#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_INT32 11 +#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32 12 +#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STRING 13 +#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STARTSTR 14 +#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_ENDSTR 15 +#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STRING 16 +#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STARTSTR 17 +#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_ENDSTR 18 + +/* google.protobuf.FieldOptions */ +#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 +#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 +#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 +#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 +#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE_INT32 6 +#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED_BOOL 7 +#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED_BOOL 8 +#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_LAZY_BOOL 9 +#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_STRING 10 +#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_STARTSTR 11 +#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_ENDSTR 12 +#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_WEAK_BOOL 13 + +/* google.protobuf.FileDescriptorProto */ +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_STARTSUBMSG 2 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 3 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSUBMSG 4 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSUBMSG 5 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 6 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_STARTSUBMSG 7 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_STARTSEQ 8 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_ENDSEQ 9 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_ENDSUBMSG 10 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 11 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 12 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 13 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSEQ 14 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSEQ 15 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSUBMSG 16 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSEQ 17 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSEQ 18 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSUBMSG 19 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 20 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_ENDSUBMSG 21 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_STRING 22 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_STARTSTR 23 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_ENDSTR 24 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_STRING 25 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_STARTSTR 26 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_ENDSTR 27 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSEQ 28 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSEQ 29 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STRING 30 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSTR 31 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSTR 32 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PUBLIC_DEPENDENCY_STARTSEQ 33 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PUBLIC_DEPENDENCY_ENDSEQ 34 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PUBLIC_DEPENDENCY_INT32 35 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_WEAK_DEPENDENCY_STARTSEQ 36 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_WEAK_DEPENDENCY_ENDSEQ 37 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_WEAK_DEPENDENCY_INT32 38 + +/* google.protobuf.FileDescriptorSet */ +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STARTSUBMSG 2 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STARTSEQ 3 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSEQ 4 +#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSUBMSG 5 + +/* google.protobuf.FileOptions */ +#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 +#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 +#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 +#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 +#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STRING 6 +#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STARTSTR 7 +#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_ENDSTR 8 +#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STRING 9 +#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STARTSTR 10 +#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_ENDSTR 11 +#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR_INT32 12 +#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES_BOOL 13 +#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_GO_PACKAGE_STRING 14 +#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_GO_PACKAGE_STARTSTR 15 +#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_GO_PACKAGE_ENDSTR 16 +#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES_BOOL 17 +#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES_BOOL 18 +#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES_BOOL 19 +#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH_BOOL 20 + +/* google.protobuf.MessageOptions */ +#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 +#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 +#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 +#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 +#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT_BOOL 6 +#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR_BOOL 7 + +/* google.protobuf.MethodDescriptorProto */ +#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 2 +#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 3 +#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_STRING 4 +#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_STARTSTR 5 +#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_ENDSTR 6 +#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STRING 7 +#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STARTSTR 8 +#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_ENDSTR 9 +#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_STRING 10 +#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_STARTSTR 11 +#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_ENDSTR 12 + +/* google.protobuf.MethodOptions */ +#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 +#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 +#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 +#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 + +/* google.protobuf.ServiceDescriptorProto */ +#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_STARTSUBMSG 2 +#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 3 +#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_STARTSEQ 4 +#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_ENDSEQ 5 +#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_ENDSUBMSG 6 +#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 7 +#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_STRING 8 +#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_STARTSTR 9 +#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_ENDSTR 10 + +/* google.protobuf.ServiceOptions */ +#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 +#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 +#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 +#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 + +/* google.protobuf.SourceCodeInfo */ +#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_STARTSUBMSG 2 +#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_STARTSEQ 3 +#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_ENDSEQ 4 +#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_ENDSUBMSG 5 + +/* google.protobuf.SourceCodeInfo.Location */ +#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_STARTSEQ 2 +#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_ENDSEQ 3 +#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_INT32 4 +#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_STARTSEQ 5 +#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_ENDSEQ 6 +#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_INT32 7 +#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_COMMENTS_STRING 8 +#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_COMMENTS_STARTSTR 9 +#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_COMMENTS_ENDSTR 10 +#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_TRAILING_COMMENTS_STRING 11 +#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_TRAILING_COMMENTS_STARTSTR 12 +#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_TRAILING_COMMENTS_ENDSTR 13 + +/* google.protobuf.UninterpretedOption */ +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_STARTSUBMSG 2 +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_STARTSEQ 3 +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_ENDSEQ 4 +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_ENDSUBMSG 5 +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STRING 6 +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STARTSTR 7 +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_ENDSTR 8 +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE_UINT64 9 +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE_INT64 10 +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE_DOUBLE 11 +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STRING 12 +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STARTSTR 13 +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_ENDSTR 14 +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STRING 15 +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STARTSTR 16 +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_ENDSTR 17 + +/* google.protobuf.UninterpretedOption.NamePart */ +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STRING 2 +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STARTSTR 3 +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_ENDSTR 4 +#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION_BOOL 5 + +const upb_symtab *upbdefs_google_protobuf_descriptor(const void *owner); + +/* MessageDefs */ +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_DescriptorProto(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto.ExtensionRange"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumDescriptorProto(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumDescriptorProto"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumOptions(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumOptions"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumValueDescriptorProto(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumValueDescriptorProto"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumValueOptions(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumValueOptions"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FieldDescriptorProto(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FieldDescriptorProto"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FieldOptions(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FieldOptions"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FileDescriptorProto(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FileDescriptorProto"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FileDescriptorSet(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FileDescriptorSet"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FileOptions(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FileOptions"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_MessageOptions(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.MessageOptions"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_MethodDescriptorProto(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.MethodDescriptorProto"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_MethodOptions(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.MethodOptions"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_ServiceDescriptorProto(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.ServiceDescriptorProto"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_ServiceOptions(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.ServiceOptions"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.SourceCodeInfo"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_Location(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.SourceCodeInfo.Location"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.UninterpretedOption"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_NamePart(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.UninterpretedOption.NamePart"); + assert(m); + return m; +} + + +/* EnumDefs */ +UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Label(const upb_symtab *s) { + const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FieldDescriptorProto.Label"); + assert(e); + return e; +} +UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Type(const upb_symtab *s) { + const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FieldDescriptorProto.Type"); + assert(e); + return e; +} +UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FieldOptions_CType(const upb_symtab *s) { + const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FieldOptions.CType"); + assert(e); + return e; +} +UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FileOptions_OptimizeMode(const upb_symtab *s) { + const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FileOptions.OptimizeMode"); + assert(e); + return e; +} + +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_end(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto_ExtensionRange(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_start(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto_ExtensionRange(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_enum_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 4); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_extension(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 6); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_extension_range(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 5); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_field(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_nested_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 7); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumDescriptorProto(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumDescriptorProto(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumDescriptorProto(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_allow_alias(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumOptions(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumOptions(s), 999); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueDescriptorProto(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_number(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueDescriptorProto(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueDescriptorProto(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueOptions(s), 999); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_default_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 7); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_extendee(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_label(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 4); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_number(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 8); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 5); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_type_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 6); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_ctype(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_deprecated(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_experimental_map_key(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 9); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_lazy(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 5); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_packed(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 999); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_weak(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 10); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_dependency(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_enum_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 5); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_extension(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 7); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_message_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 4); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 8); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_package(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_public_dependency(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 10); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_service(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 6); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_source_code_info(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 9); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_weak_dependency(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 11); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorSet_file(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorSet(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_cc_generic_services(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 16); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_go_package(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 11); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_generate_equals_and_hash(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 20); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_generic_services(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 17); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_multiple_files(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 10); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_outer_classname(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 8); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_package(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_optimize_for(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 9); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_py_generic_services(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 18); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 999); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_message_set_wire_format(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_no_standard_descriptor_accessor(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 999); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_input_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 4); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_output_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodOptions(s), 999); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_method(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceDescriptorProto(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceDescriptorProto(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceDescriptorProto(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceOptions(s), 999); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_leading_comments(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_path(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_span(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_trailing_comments(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 4); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_location(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_is_extension(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption_NamePart(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_name_part(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption_NamePart(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_aggregate_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 8); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_double_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 6); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_identifier_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_negative_int_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 5); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_positive_int_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 4); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_string_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 7); } + +UPB_END_EXTERN_C + +#ifdef __cplusplus + +namespace upbdefs { +namespace google { +namespace protobuf { +namespace descriptor { +inline upb::reffed_ptr<const upb::SymbolTable> SymbolTable() { + const upb::SymbolTable* s = upbdefs_google_protobuf_descriptor(&s); + return upb::reffed_ptr<const upb::SymbolTable>(s, &s); +} +} /* namespace descriptor */ +} /* namespace protobuf */ +} /* namespace google */ + +#define RETURN_REFFED(type, func) \ + const type* obj = func(upbdefs::google::protobuf::descriptor::SymbolTable().get()); \ + return upb::reffed_ptr<const type>(obj); + +namespace google { +namespace protobuf { +namespace DescriptorProto { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_DescriptorProto) } +inline upb::reffed_ptr<const upb::FieldDef> enum_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_enum_type) } +inline upb::reffed_ptr<const upb::FieldDef> extension() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_extension) } +inline upb::reffed_ptr<const upb::FieldDef> extension_range() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_extension_range) } +inline upb::reffed_ptr<const upb::FieldDef> field() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_field) } +inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_name) } +inline upb::reffed_ptr<const upb::FieldDef> nested_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_nested_type) } +inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_options) } +} /* namespace DescriptorProto */ +} /* namespace protobuf */ +} /* namespace google */ + +namespace google { +namespace protobuf { +namespace DescriptorProto { +namespace ExtensionRange { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_DescriptorProto_ExtensionRange) } +inline upb::reffed_ptr<const upb::FieldDef> end() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_ExtensionRange_end) } +inline upb::reffed_ptr<const upb::FieldDef> start() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_ExtensionRange_start) } +} /* namespace ExtensionRange */ +} /* namespace DescriptorProto */ +} /* namespace protobuf */ +} /* namespace google */ + +namespace google { +namespace protobuf { +namespace EnumDescriptorProto { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumDescriptorProto) } +inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumDescriptorProto_name) } +inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumDescriptorProto_options) } +inline upb::reffed_ptr<const upb::FieldDef> value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumDescriptorProto_value) } +} /* namespace EnumDescriptorProto */ +} /* namespace protobuf */ +} /* namespace google */ + +namespace google { +namespace protobuf { +namespace EnumOptions { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumOptions) } +inline upb::reffed_ptr<const upb::FieldDef> allow_alias() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumOptions_allow_alias) } +inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumOptions_uninterpreted_option) } +} /* namespace EnumOptions */ +} /* namespace protobuf */ +} /* namespace google */ + +namespace google { +namespace protobuf { +namespace EnumValueDescriptorProto { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumValueDescriptorProto) } +inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueDescriptorProto_name) } +inline upb::reffed_ptr<const upb::FieldDef> number() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueDescriptorProto_number) } +inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueDescriptorProto_options) } +} /* namespace EnumValueDescriptorProto */ +} /* namespace protobuf */ +} /* namespace google */ + +namespace google { +namespace protobuf { +namespace EnumValueOptions { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumValueOptions) } +inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueOptions_uninterpreted_option) } +} /* namespace EnumValueOptions */ +} /* namespace protobuf */ +} /* namespace google */ + +namespace google { +namespace protobuf { +namespace FieldDescriptorProto { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FieldDescriptorProto) } +inline upb::reffed_ptr<const upb::FieldDef> default_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_default_value) } +inline upb::reffed_ptr<const upb::FieldDef> extendee() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_extendee) } +inline upb::reffed_ptr<const upb::FieldDef> label() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_label) } +inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_name) } +inline upb::reffed_ptr<const upb::FieldDef> number() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_number) } +inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_options) } +inline upb::reffed_ptr<const upb::FieldDef> type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_type) } +inline upb::reffed_ptr<const upb::FieldDef> type_name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_type_name) } +inline upb::reffed_ptr<const upb::EnumDef> Label() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FieldDescriptorProto_Label) } +inline upb::reffed_ptr<const upb::EnumDef> Type() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FieldDescriptorProto_Type) } +} /* namespace FieldDescriptorProto */ +} /* namespace protobuf */ +} /* namespace google */ + +namespace google { +namespace protobuf { +namespace FieldOptions { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FieldOptions) } +inline upb::reffed_ptr<const upb::FieldDef> ctype() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_ctype) } +inline upb::reffed_ptr<const upb::FieldDef> deprecated() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_deprecated) } +inline upb::reffed_ptr<const upb::FieldDef> experimental_map_key() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_experimental_map_key) } +inline upb::reffed_ptr<const upb::FieldDef> lazy() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_lazy) } +inline upb::reffed_ptr<const upb::FieldDef> packed() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_packed) } +inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_uninterpreted_option) } +inline upb::reffed_ptr<const upb::FieldDef> weak() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_weak) } +inline upb::reffed_ptr<const upb::EnumDef> CType() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FieldOptions_CType) } +} /* namespace FieldOptions */ +} /* namespace protobuf */ +} /* namespace google */ + +namespace google { +namespace protobuf { +namespace FileDescriptorProto { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FileDescriptorProto) } +inline upb::reffed_ptr<const upb::FieldDef> dependency() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_dependency) } +inline upb::reffed_ptr<const upb::FieldDef> enum_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_enum_type) } +inline upb::reffed_ptr<const upb::FieldDef> extension() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_extension) } +inline upb::reffed_ptr<const upb::FieldDef> message_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_message_type) } +inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_name) } +inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_options) } +inline upb::reffed_ptr<const upb::FieldDef> package() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_package) } +inline upb::reffed_ptr<const upb::FieldDef> public_dependency() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_public_dependency) } +inline upb::reffed_ptr<const upb::FieldDef> service() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_service) } +inline upb::reffed_ptr<const upb::FieldDef> source_code_info() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_source_code_info) } +inline upb::reffed_ptr<const upb::FieldDef> weak_dependency() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_weak_dependency) } +} /* namespace FileDescriptorProto */ +} /* namespace protobuf */ +} /* namespace google */ + +namespace google { +namespace protobuf { +namespace FileDescriptorSet { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FileDescriptorSet) } +inline upb::reffed_ptr<const upb::FieldDef> file() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorSet_file) } +} /* namespace FileDescriptorSet */ +} /* namespace protobuf */ +} /* namespace google */ + +namespace google { +namespace protobuf { +namespace FileOptions { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FileOptions) } +inline upb::reffed_ptr<const upb::FieldDef> cc_generic_services() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_cc_generic_services) } +inline upb::reffed_ptr<const upb::FieldDef> go_package() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_go_package) } +inline upb::reffed_ptr<const upb::FieldDef> java_generate_equals_and_hash() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_generate_equals_and_hash) } +inline upb::reffed_ptr<const upb::FieldDef> java_generic_services() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_generic_services) } +inline upb::reffed_ptr<const upb::FieldDef> java_multiple_files() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_multiple_files) } +inline upb::reffed_ptr<const upb::FieldDef> java_outer_classname() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_outer_classname) } +inline upb::reffed_ptr<const upb::FieldDef> java_package() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_package) } +inline upb::reffed_ptr<const upb::FieldDef> optimize_for() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_optimize_for) } +inline upb::reffed_ptr<const upb::FieldDef> py_generic_services() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_py_generic_services) } +inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_uninterpreted_option) } +inline upb::reffed_ptr<const upb::EnumDef> OptimizeMode() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FileOptions_OptimizeMode) } +} /* namespace FileOptions */ +} /* namespace protobuf */ +} /* namespace google */ + +namespace google { +namespace protobuf { +namespace MessageOptions { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_MessageOptions) } +inline upb::reffed_ptr<const upb::FieldDef> message_set_wire_format() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_message_set_wire_format) } +inline upb::reffed_ptr<const upb::FieldDef> no_standard_descriptor_accessor() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_no_standard_descriptor_accessor) } +inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_uninterpreted_option) } +} /* namespace MessageOptions */ +} /* namespace protobuf */ +} /* namespace google */ + +namespace google { +namespace protobuf { +namespace MethodDescriptorProto { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_MethodDescriptorProto) } +inline upb::reffed_ptr<const upb::FieldDef> input_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_input_type) } +inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_name) } +inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_options) } +inline upb::reffed_ptr<const upb::FieldDef> output_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_output_type) } +} /* namespace MethodDescriptorProto */ +} /* namespace protobuf */ +} /* namespace google */ + +namespace google { +namespace protobuf { +namespace MethodOptions { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_MethodOptions) } +inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodOptions_uninterpreted_option) } +} /* namespace MethodOptions */ +} /* namespace protobuf */ +} /* namespace google */ + +namespace google { +namespace protobuf { +namespace ServiceDescriptorProto { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_ServiceDescriptorProto) } +inline upb::reffed_ptr<const upb::FieldDef> method() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceDescriptorProto_method) } +inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceDescriptorProto_name) } +inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceDescriptorProto_options) } +} /* namespace ServiceDescriptorProto */ +} /* namespace protobuf */ +} /* namespace google */ + +namespace google { +namespace protobuf { +namespace ServiceOptions { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_ServiceOptions) } +inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceOptions_uninterpreted_option) } +} /* namespace ServiceOptions */ +} /* namespace protobuf */ +} /* namespace google */ + +namespace google { +namespace protobuf { +namespace SourceCodeInfo { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_SourceCodeInfo) } +inline upb::reffed_ptr<const upb::FieldDef> location() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_location) } +} /* namespace SourceCodeInfo */ +} /* namespace protobuf */ +} /* namespace google */ + +namespace google { +namespace protobuf { +namespace SourceCodeInfo { +namespace Location { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_SourceCodeInfo_Location) } +inline upb::reffed_ptr<const upb::FieldDef> leading_comments() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_leading_comments) } +inline upb::reffed_ptr<const upb::FieldDef> path() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_path) } +inline upb::reffed_ptr<const upb::FieldDef> span() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_span) } +inline upb::reffed_ptr<const upb::FieldDef> trailing_comments() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_trailing_comments) } +} /* namespace Location */ +} /* namespace SourceCodeInfo */ +} /* namespace protobuf */ +} /* namespace google */ + +namespace google { +namespace protobuf { +namespace UninterpretedOption { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_UninterpretedOption) } +inline upb::reffed_ptr<const upb::FieldDef> aggregate_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_aggregate_value) } +inline upb::reffed_ptr<const upb::FieldDef> double_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_double_value) } +inline upb::reffed_ptr<const upb::FieldDef> identifier_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_identifier_value) } +inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_name) } +inline upb::reffed_ptr<const upb::FieldDef> negative_int_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_negative_int_value) } +inline upb::reffed_ptr<const upb::FieldDef> positive_int_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_positive_int_value) } +inline upb::reffed_ptr<const upb::FieldDef> string_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_string_value) } +} /* namespace UninterpretedOption */ +} /* namespace protobuf */ +} /* namespace google */ + +namespace google { +namespace protobuf { +namespace UninterpretedOption { +namespace NamePart { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_UninterpretedOption_NamePart) } +inline upb::reffed_ptr<const upb::FieldDef> is_extension() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_NamePart_is_extension) } +inline upb::reffed_ptr<const upb::FieldDef> name_part() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_NamePart_name_part) } +} /* namespace NamePart */ +} /* namespace UninterpretedOption */ +} /* namespace protobuf */ +} /* namespace google */ + +} /* namespace upbdefs */ + + +#undef RETURN_REFFED +#endif /* __cplusplus */ + +#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_ */ /* * upb - a minimalist implementation of protocol buffers. * @@ -6953,134 +7107,111 @@ class CodeCache; class Decoder; class DecoderMethod; class DecoderMethodOptions; -} // namespace pb -} // namespace upb +} /* namespace pb */ +} /* namespace upb */ #endif -UPB_DECLARE_TYPE(upb::pb::CodeCache, upb_pbcodecache); -UPB_DECLARE_TYPE(upb::pb::Decoder, upb_pbdecoder); -UPB_DECLARE_TYPE(upb::pb::DecoderMethod, upb_pbdecodermethod); -UPB_DECLARE_TYPE(upb::pb::DecoderMethodOptions, upb_pbdecodermethodopts); +UPB_DECLARE_TYPE(upb::pb::CodeCache, upb_pbcodecache) +UPB_DECLARE_TYPE(upb::pb::Decoder, upb_pbdecoder) +UPB_DECLARE_TYPE(upb::pb::DecoderMethodOptions, upb_pbdecodermethodopts) + +UPB_DECLARE_DERIVED_TYPE(upb::pb::DecoderMethod, upb::RefCounted, + upb_pbdecodermethod, upb_refcounted) -// The parameters one uses to construct a DecoderMethod. -// TODO(haberman): move allowjit here? Seems more convenient for users. -UPB_DEFINE_CLASS0(upb::pb::DecoderMethodOptions, +#ifdef __cplusplus + +/* The parameters one uses to construct a DecoderMethod. + * TODO(haberman): move allowjit here? Seems more convenient for users. + * TODO(haberman): move this to be heap allocated for ABI stability. */ +class upb::pb::DecoderMethodOptions { public: - // Parameter represents the destination handlers that this method will push - // to. + /* Parameter represents the destination handlers that this method will push + * to. */ explicit DecoderMethodOptions(const Handlers* dest_handlers); - // Should the decoder push submessages to lazy handlers for fields that have - // them? The caller should set this iff the lazy handlers expect data that is - // in protobuf binary format and the caller wishes to lazy parse it. + /* Should the decoder push submessages to lazy handlers for fields that have + * them? The caller should set this iff the lazy handlers expect data that is + * in protobuf binary format and the caller wishes to lazy parse it. */ void set_lazy(bool lazy); -, -UPB_DEFINE_STRUCT0(upb_pbdecodermethodopts, +#else +struct upb_pbdecodermethodopts { +#endif const upb_handlers *handlers; bool lazy; -)); +}; + +#ifdef __cplusplus -// Represents the code to parse a protobuf according to a destination Handlers. -UPB_DEFINE_CLASS1(upb::pb::DecoderMethod, upb::RefCounted, +/* Represents the code to parse a protobuf according to a destination + * Handlers. */ +class upb::pb::DecoderMethod { public: - // From upb::ReferenceCounted. - void Ref(const void* owner) const; - void Unref(const void* owner) const; - void DonateRef(const void* from, const void* to) const; - void CheckRef(const void* owner) const; - - // The destination handlers that are statically bound to this method. - // This method is only capable of outputting to a sink that uses these - // handlers. + /* Include base methods from upb::ReferenceCounted. */ + UPB_REFCOUNTED_CPPMETHODS + + /* The destination handlers that are statically bound to this method. + * This method is only capable of outputting to a sink that uses these + * handlers. */ const Handlers* dest_handlers() const; - // The input handlers for this decoder method. + /* The input handlers for this decoder method. */ const BytesHandler* input_handler() const; - // Whether this method is native. + /* Whether this method is native. */ bool is_native() const; - // Convenience method for generating a DecoderMethod without explicitly - // creating a CodeCache. + /* Convenience method for generating a DecoderMethod without explicitly + * creating a CodeCache. */ static reffed_ptr<const DecoderMethod> New(const DecoderMethodOptions& opts); private: - UPB_DISALLOW_POD_OPS(DecoderMethod, upb::pb::DecoderMethod); -, -UPB_DEFINE_STRUCT(upb_pbdecodermethod, upb_refcounted, - // While compiling, the base is relative in "ofs", after compiling it is - // absolute in "ptr". - union { - uint32_t ofs; // PC offset of method. - void *ptr; // Pointer to bytecode or machine code for this method. - } code_base; - - // The decoder method group to which this method belongs. We own a ref. - // Owning a ref on the entire group is more coarse-grained than is strictly - // necessary; all we truly require is that methods we directly reference - // outlive us, while the group could contain many other messages we don't - // require. But the group represents the messages that were - // allocated+compiled together, so it makes the most sense to free them - // together also. - const upb_refcounted *group; - - // Whether this method is native code or bytecode. - bool is_native_; - - // The handler one calls to invoke this method. - upb_byteshandler input_handler_; - - // The destination handlers this method is bound to. We own a ref. - const upb_handlers *dest_handlers_; + UPB_DISALLOW_POD_OPS(DecoderMethod, upb::pb::DecoderMethod) +}; - // Dispatch table -- used by both bytecode decoder and JIT when encountering a - // field number that wasn't the one we were expecting to see. See - // decoder.int.h for the layout of this table. - upb_inttable dispatch; -)); +#endif -// Preallocation hint: decoder won't allocate more bytes than this when first -// constructed. This hint may be an overestimate for some build configurations. -// But if the decoder library is upgraded without recompiling the application, -// it may be an underestimate. +/* Preallocation hint: decoder won't allocate more bytes than this when first + * constructed. This hint may be an overestimate for some build configurations. + * But if the decoder library is upgraded without recompiling the application, + * it may be an underestimate. */ #define UPB_PB_DECODER_SIZE 4400 #ifdef __cplusplus -// A Decoder receives binary protobuf data on its input sink and pushes the -// decoded data to its output sink. +/* A Decoder receives binary protobuf data on its input sink and pushes the + * decoded data to its output sink. */ class upb::pb::Decoder { public: - // Constructs a decoder instance for the given method, which must outlive this - // decoder. Any errors during parsing will be set on the given status, which - // must also outlive this decoder. - // - // The sink must match the given method. + /* Constructs a decoder instance for the given method, which must outlive this + * decoder. Any errors during parsing will be set on the given status, which + * must also outlive this decoder. + * + * The sink must match the given method. */ static Decoder* Create(Environment* env, const DecoderMethod* method, Sink* output); - // Returns the DecoderMethod this decoder is parsing from. + /* Returns the DecoderMethod this decoder is parsing from. */ const DecoderMethod* method() const; - // The sink on which this decoder receives input. + /* The sink on which this decoder receives input. */ BytesSink* input(); - // Returns number of bytes successfully parsed. - // - // This can be useful for determining the stream position where an error - // occurred. - // - // This value may not be up-to-date when called from inside a parsing - // callback. + /* Returns number of bytes successfully parsed. + * + * This can be useful for determining the stream position where an error + * occurred. + * + * This value may not be up-to-date when called from inside a parsing + * callback. */ uint64_t BytesParsed() const; - // Gets/sets the parsing nexting limit. If the total number of nested - // submessages and repeated fields hits this limit, parsing will fail. This - // is a resource limit that controls the amount of memory used by the parsing - // stack. - // - // Setting the limit will fail if the parser is currently suspended at a depth - // greater than this, or if memory allocation of the stack fails. + /* Gets/sets the parsing nexting limit. If the total number of nested + * submessages and repeated fields hits this limit, parsing will fail. This + * is a resource limit that controls the amount of memory used by the parsing + * stack. + * + * Setting the limit will fail if the parser is currently suspended at a depth + * greater than this, or if memory allocation of the stack fails. */ size_t max_nesting() const; bool set_max_nesting(size_t max); @@ -7089,57 +7220,62 @@ class upb::pb::Decoder { static const size_t kSize = UPB_PB_DECODER_SIZE; private: - UPB_DISALLOW_POD_OPS(Decoder, upb::pb::Decoder); + UPB_DISALLOW_POD_OPS(Decoder, upb::pb::Decoder) }; -#endif // __cplusplus +#endif /* __cplusplus */ -// A class for caching protobuf processing code, whether bytecode for the -// interpreted decoder or machine code for the JIT. -// -// This class is not thread-safe. -UPB_DEFINE_CLASS0(upb::pb::CodeCache, +#ifdef __cplusplus + +/* A class for caching protobuf processing code, whether bytecode for the + * interpreted decoder or machine code for the JIT. + * + * This class is not thread-safe. + * + * TODO(haberman): move this to be heap allocated for ABI stability. */ +class upb::pb::CodeCache { public: CodeCache(); ~CodeCache(); - // Whether the cache is allowed to generate machine code. Defaults to true. - // There is no real reason to turn it off except for testing or if you are - // having a specific problem with the JIT. - // - // Note that allow_jit = true does not *guarantee* that the code will be JIT - // compiled. If this platform is not supported or the JIT was not compiled - // in, the code may still be interpreted. + /* Whether the cache is allowed to generate machine code. Defaults to true. + * There is no real reason to turn it off except for testing or if you are + * having a specific problem with the JIT. + * + * Note that allow_jit = true does not *guarantee* that the code will be JIT + * compiled. If this platform is not supported or the JIT was not compiled + * in, the code may still be interpreted. */ bool allow_jit() const; - // This may only be called when the object is first constructed, and prior to - // any code generation, otherwise returns false and does nothing. + /* This may only be called when the object is first constructed, and prior to + * any code generation, otherwise returns false and does nothing. */ bool set_allow_jit(bool allow); - // Returns a DecoderMethod that can push data to the given handlers. - // If a suitable method already exists, it will be returned from the cache. - // - // Specifying the destination handlers here allows the DecoderMethod to be - // statically bound to the destination handlers if possible, which can allow - // more efficient decoding. However the returned method may or may not - // actually be statically bound. But in all cases, the returned method can - // push data to the given handlers. + /* Returns a DecoderMethod that can push data to the given handlers. + * If a suitable method already exists, it will be returned from the cache. + * + * Specifying the destination handlers here allows the DecoderMethod to be + * statically bound to the destination handlers if possible, which can allow + * more efficient decoding. However the returned method may or may not + * actually be statically bound. But in all cases, the returned method can + * push data to the given handlers. */ const DecoderMethod *GetDecoderMethod(const DecoderMethodOptions& opts); - // If/when someone needs to explicitly create a dynamically-bound - // DecoderMethod*, we can add a method to get it here. + /* If/when someone needs to explicitly create a dynamically-bound + * DecoderMethod*, we can add a method to get it here. */ private: - UPB_DISALLOW_COPY_AND_ASSIGN(CodeCache); -, -UPB_DEFINE_STRUCT0(upb_pbcodecache, + UPB_DISALLOW_COPY_AND_ASSIGN(CodeCache) +#else +struct upb_pbcodecache { +#endif bool allow_jit_; - // Array of mgroups. + /* Array of mgroups. */ upb_inttable groups; -)); +}; -UPB_BEGIN_EXTERN_C // { +UPB_BEGIN_EXTERN_C upb_pbdecoder *upb_pbdecoder_create(upb_env *e, const upb_pbdecodermethod *method, @@ -7155,12 +7291,10 @@ void upb_pbdecodermethodopts_init(upb_pbdecodermethodopts *opts, const upb_handlers *h); void upb_pbdecodermethodopts_setlazy(upb_pbdecodermethodopts *opts, bool lazy); -void upb_pbdecodermethod_ref(const upb_pbdecodermethod *m, const void *owner); -void upb_pbdecodermethod_unref(const upb_pbdecodermethod *m, const void *owner); -void upb_pbdecodermethod_donateref(const upb_pbdecodermethod *m, - const void *from, const void *to); -void upb_pbdecodermethod_checkref(const upb_pbdecodermethod *m, - const void *owner); + +/* Include refcounted methods like upb_pbdecodermethod_ref(). */ +UPB_REFCOUNTED_CMETHODS(upb_pbdecodermethod, upb_pbdecodermethod_upcast) + const upb_handlers *upb_pbdecodermethod_desthandlers( const upb_pbdecodermethod *m); const upb_byteshandler *upb_pbdecodermethod_inputhandler( @@ -7176,7 +7310,7 @@ bool upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow); const upb_pbdecodermethod *upb_pbcodecache_getdecodermethod( upb_pbcodecache *c, const upb_pbdecodermethodopts *opts); -UPB_END_EXTERN_C // } +UPB_END_EXTERN_C #ifdef __cplusplus @@ -7184,7 +7318,7 @@ namespace upb { namespace pb { -// static +/* static */ inline Decoder* Decoder::Create(Environment* env, const DecoderMethod* m, Sink* sink) { return upb_pbdecoder_create(env, m, sink); @@ -7213,18 +7347,6 @@ inline void DecoderMethodOptions::set_lazy(bool lazy) { upb_pbdecodermethodopts_setlazy(this, lazy); } -inline void DecoderMethod::Ref(const void *owner) const { - upb_pbdecodermethod_ref(this, owner); -} -inline void DecoderMethod::Unref(const void *owner) const { - upb_pbdecodermethod_unref(this, owner); -} -inline void DecoderMethod::DonateRef(const void *from, const void *to) const { - upb_pbdecodermethod_donateref(this, from, to); -} -inline void DecoderMethod::CheckRef(const void *owner) const { - upb_pbdecodermethod_checkref(this, owner); -} inline const Handlers* DecoderMethod::dest_handlers() const { return upb_pbdecodermethod_desthandlers(this); } @@ -7234,7 +7356,7 @@ inline const BytesHandler* DecoderMethod::input_handler() const { inline bool DecoderMethod::is_native() const { return upb_pbdecodermethod_isnative(this); } -// static +/* static */ inline reffed_ptr<const DecoderMethod> DecoderMethod::New( const DecoderMethodOptions &opts) { const upb_pbdecodermethod *m = upb_pbdecodermethod_new(&opts, &m); @@ -7258,33 +7380,44 @@ inline const DecoderMethod *CodeCache::GetDecoderMethod( return upb_pbcodecache_getdecodermethod(this, &opts); } -} // namespace pb -} // namespace upb +} /* namespace pb */ +} /* namespace upb */ -#endif // __cplusplus +#endif /* __cplusplus */ #endif /* UPB_DECODER_H_ */ -// Opcode definitions. The canonical meaning of each opcode is its -// implementation in the interpreter (the JIT is written to match this). -// -// All instructions have the opcode in the low byte. -// Instruction format for most instructions is: -// -// +-------------------+--------+ -// | arg (24) | op (8) | -// +-------------------+--------+ -// -// Exceptions are indicated below. A few opcodes are multi-word. +/* C++ names are not actually used since this type isn't exposed to users. */ +#ifdef __cplusplus +namespace upb { +namespace pb { +class MessageGroup; +} /* namespace pb */ +} /* namespace upb */ +#endif +UPB_DECLARE_DERIVED_TYPE(upb::pb::MessageGroup, upb::RefCounted, + mgroup, upb_refcounted) + +/* Opcode definitions. The canonical meaning of each opcode is its + * implementation in the interpreter (the JIT is written to match this). + * + * All instructions have the opcode in the low byte. + * Instruction format for most instructions is: + * + * +-------------------+--------+ + * | arg (24) | op (8) | + * +-------------------+--------+ + * + * Exceptions are indicated below. A few opcodes are multi-word. */ typedef enum { - // Opcodes 1-8, 13, 15-18 parse their respective descriptor types. - // Arg for all of these is the upb selector for this field. + /* Opcodes 1-8, 13, 15-18 parse their respective descriptor types. + * Arg for all of these is the upb selector for this field. */ #define T(type) OP_PARSE_ ## type = UPB_DESCRIPTOR_TYPE_ ## type T(DOUBLE), T(FLOAT), T(INT64), T(UINT64), T(INT32), T(FIXED64), T(FIXED32), T(BOOL), T(UINT32), T(SFIXED32), T(SFIXED64), T(SINT32), T(SINT64), #undef T - OP_STARTMSG = 9, // No arg. - OP_ENDMSG = 10, // No arg. + OP_STARTMSG = 9, /* No arg. */ + OP_ENDMSG = 10, /* No arg. */ OP_STARTSEQ = 11, OP_ENDSEQ = 12, OP_STARTSUBMSG = 14, @@ -7293,148 +7426,185 @@ typedef enum { OP_STRING = 21, OP_ENDSTR = 22, - OP_PUSHTAGDELIM = 23, // No arg. - OP_PUSHLENDELIM = 24, // No arg. - OP_POP = 25, // No arg. - OP_SETDELIM = 26, // No arg. - OP_SETBIGGROUPNUM = 27, // two words: | unused (24) | opc || groupnum (32) | + OP_PUSHTAGDELIM = 23, /* No arg. */ + OP_PUSHLENDELIM = 24, /* No arg. */ + OP_POP = 25, /* No arg. */ + OP_SETDELIM = 26, /* No arg. */ + OP_SETBIGGROUPNUM = 27, /* two words: + * | unused (24) | opc (8) | + * | groupnum (32) | */ OP_CHECKDELIM = 28, OP_CALL = 29, OP_RET = 30, OP_BRANCH = 31, - // Different opcodes depending on how many bytes expected. - OP_TAG1 = 32, // | expected tag (16) | jump target (8) | opc (8) | - OP_TAG2 = 33, // | expected tag (16) | jump target (8) | opc (8) | - OP_TAGN = 34, // three words: - // | unused (16) | jump target(8) | opc (8) | - // | expected tag 1 (32) | - // | expected tag 2 (32) | + /* Different opcodes depending on how many bytes expected. */ + OP_TAG1 = 32, /* | match tag (16) | jump target (8) | opc (8) | */ + OP_TAG2 = 33, /* | match tag (16) | jump target (8) | opc (8) | */ + OP_TAGN = 34, /* three words: */ + /* | unused (16) | jump target(8) | opc (8) | */ + /* | match tag 1 (32) | */ + /* | match tag 2 (32) | */ - OP_SETDISPATCH = 35, // N words: - // | unused (24) | opc | - // | upb_inttable* (32 or 64) | + OP_SETDISPATCH = 35, /* N words: */ + /* | unused (24) | opc | */ + /* | upb_inttable* (32 or 64) | */ - OP_DISPATCH = 36, // No arg. + OP_DISPATCH = 36, /* No arg. */ - OP_HALT = 37, // No arg. + OP_HALT = 37 /* No arg. */ } opcode; #define OP_MAX OP_HALT UPB_INLINE opcode getop(uint32_t instr) { return instr & 0xff; } -// Method group; represents a set of decoder methods that had their code -// emitted together, and must therefore be freed together. Immutable once -// created. It is possible we may want to expose this to users at some point. -// -// Overall ownership of Decoder objects looks like this: -// -// +----------+ -// | | <---> DecoderMethod -// | method | -// CodeCache ---> | group | <---> DecoderMethod -// | | -// | (mgroup) | <---> DecoderMethod -// +----------+ -typedef struct { +/* Method group; represents a set of decoder methods that had their code + * emitted together, and must therefore be freed together. Immutable once + * created. It is possible we may want to expose this to users at some point. + * + * Overall ownership of Decoder objects looks like this: + * + * +----------+ + * | | <---> DecoderMethod + * | method | + * CodeCache ---> | group | <---> DecoderMethod + * | | + * | (mgroup) | <---> DecoderMethod + * +----------+ + */ +struct mgroup { upb_refcounted base; - // Maps upb_msgdef/upb_handlers -> upb_pbdecodermethod. We own refs on the - // methods. + /* Maps upb_msgdef/upb_handlers -> upb_pbdecodermethod. We own refs on the + * methods. */ upb_inttable methods; - // When we add the ability to link to previously existing mgroups, we'll - // need an array of mgroups we reference here, and own refs on them. + /* When we add the ability to link to previously existing mgroups, we'll + * need an array of mgroups we reference here, and own refs on them. */ - // The bytecode for our methods, if any exists. Owned by us. + /* The bytecode for our methods, if any exists. Owned by us. */ uint32_t *bytecode; uint32_t *bytecode_end; #ifdef UPB_USE_JIT_X64 - // JIT-generated machine code, if any. + /* JIT-generated machine code, if any. */ upb_string_handlerfunc *jit_code; - // The size of the jit_code (required to munmap()). + /* The size of the jit_code (required to munmap()). */ size_t jit_size; char *debug_info; void *dl; #endif -} mgroup; - -// The maximum that any submessages can be nested. Matches proto2's limit. -// This specifies the size of the decoder's statically-sized array and therefore -// setting it high will cause the upb::pb::Decoder object to be larger. -// -// If necessary we can add a runtime-settable property to Decoder that allow -// this to be larger than the compile-time setting, but this would add -// complexity, particularly since we would have to decide how/if to give users -// the ability to set a custom memory allocation function. +}; + +/* The maximum that any submessages can be nested. Matches proto2's limit. + * This specifies the size of the decoder's statically-sized array and therefore + * setting it high will cause the upb::pb::Decoder object to be larger. + * + * If necessary we can add a runtime-settable property to Decoder that allow + * this to be larger than the compile-time setting, but this would add + * complexity, particularly since we would have to decide how/if to give users + * the ability to set a custom memory allocation function. */ #define UPB_DECODER_MAX_NESTING 64 -// Internal-only struct used by the decoder. +/* Internal-only struct used by the decoder. */ typedef struct { - // Space optimization note: we store two pointers here that the JIT - // doesn't need at all; the upb_handlers* inside the sink and - // the dispatch table pointer. We can optimze so that the JIT uses - // smaller stack frames than the interpreter. The only thing we need - // to guarantee is that the fallback routines can find end_ofs. + /* Space optimization note: we store two pointers here that the JIT + * doesn't need at all; the upb_handlers* inside the sink and + * the dispatch table pointer. We can optimze so that the JIT uses + * smaller stack frames than the interpreter. The only thing we need + * to guarantee is that the fallback routines can find end_ofs. */ upb_sink sink; - // The absolute stream offset of the end-of-frame delimiter. - // Non-delimited frames (groups and non-packed repeated fields) reuse the - // delimiter of their parent, even though the frame may not end there. - // - // NOTE: the JIT stores a slightly different value here for non-top frames. - // It stores the value relative to the end of the enclosed message. But the - // top frame is still stored the same way, which is important for ensuring - // that calls from the JIT into C work correctly. + /* The absolute stream offset of the end-of-frame delimiter. + * Non-delimited frames (groups and non-packed repeated fields) reuse the + * delimiter of their parent, even though the frame may not end there. + * + * NOTE: the JIT stores a slightly different value here for non-top frames. + * It stores the value relative to the end of the enclosed message. But the + * top frame is still stored the same way, which is important for ensuring + * that calls from the JIT into C work correctly. */ uint64_t end_ofs; const uint32_t *base; - // 0 indicates a length-delimited field. - // A positive number indicates a known group. - // A negative number indicates an unknown group. + /* 0 indicates a length-delimited field. + * A positive number indicates a known group. + * A negative number indicates an unknown group. */ int32_t groupnum; - upb_inttable *dispatch; // Not used by the JIT. + upb_inttable *dispatch; /* Not used by the JIT. */ } upb_pbdecoder_frame; +struct upb_pbdecodermethod { + upb_refcounted base; + + /* While compiling, the base is relative in "ofs", after compiling it is + * absolute in "ptr". */ + union { + uint32_t ofs; /* PC offset of method. */ + void *ptr; /* Pointer to bytecode or machine code for this method. */ + } code_base; + + /* The decoder method group to which this method belongs. We own a ref. + * Owning a ref on the entire group is more coarse-grained than is strictly + * necessary; all we truly require is that methods we directly reference + * outlive us, while the group could contain many other messages we don't + * require. But the group represents the messages that were + * allocated+compiled together, so it makes the most sense to free them + * together also. */ + const upb_refcounted *group; + + /* Whether this method is native code or bytecode. */ + bool is_native_; + + /* The handler one calls to invoke this method. */ + upb_byteshandler input_handler_; + + /* The destination handlers this method is bound to. We own a ref. */ + const upb_handlers *dest_handlers_; + + /* Dispatch table -- used by both bytecode decoder and JIT when encountering a + * field number that wasn't the one we were expecting to see. See + * decoder.int.h for the layout of this table. */ + upb_inttable dispatch; +}; + struct upb_pbdecoder { upb_env *env; - // Our input sink. + /* Our input sink. */ upb_bytessink input_; - // The decoder method we are parsing with (owned). + /* The decoder method we are parsing with (owned). */ const upb_pbdecodermethod *method_; size_t call_len; const uint32_t *pc, *last; - // Current input buffer and its stream offset. + /* Current input buffer and its stream offset. */ const char *buf, *ptr, *end, *checkpoint; - // End of the delimited region, relative to ptr, or NULL if not in this buf. + /* End of the delimited region, relative to ptr, NULL if not in this buf. */ const char *delim_end; - // End of the delimited region, relative to ptr, or end if not in this buf. + /* End of the delimited region, relative to ptr, end if not in this buf. */ const char *data_end; - // Overall stream offset of "buf." + /* Overall stream offset of "buf." */ uint64_t bufstart_ofs; - // Buffer for residual bytes not parsed from the previous buffer. - // The maximum number of residual bytes we require is 12; a five-byte - // unknown tag plus an eight-byte value, less one because the value - // is only a partial value. + /* Buffer for residual bytes not parsed from the previous buffer. + * The maximum number of residual bytes we require is 12; a five-byte + * unknown tag plus an eight-byte value, less one because the value + * is only a partial value. */ char residual[12]; char *residual_end; - // Stores the user buffer passed to our decode function. + /* Stores the user buffer passed to our decode function. */ const char *buf_param; size_t size_param; const upb_bufhandle *handle; - // Our internal stack. + /* Our internal stack. */ upb_pbdecoder_frame *stack, *top, *limit; const uint32_t **callstack; size_t stack_size; @@ -7442,22 +7612,22 @@ struct upb_pbdecoder { upb_status *status; #ifdef UPB_USE_JIT_X64 - // Used momentarily by the generated code to store a value while a user - // function is called. + /* Used momentarily by the generated code to store a value while a user + * function is called. */ uint32_t tmp_len; const void *saved_rsp; #endif }; -// Decoder entry points; used as handlers. +/* Decoder entry points; used as handlers. */ void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint); void *upb_pbdecoder_startjit(void *closure, const void *hd, size_t size_hint); size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf, size_t size, const upb_bufhandle *handle); bool upb_pbdecoder_end(void *closure, const void *handler_data); -// Decoder-internal functions that the JIT calls to handle fallback paths. +/* Decoder-internal functions that the JIT calls to handle fallback paths. */ int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf, size_t size, const upb_bufhandle *handle); size_t upb_pbdecoder_suspend(upb_pbdecoder *d); @@ -7469,41 +7639,42 @@ int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32); int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64); void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg); -// Error messages that are shared between the bytecode and JIT decoders. +/* Error messages that are shared between the bytecode and JIT decoders. */ extern const char *kPbDecoderStackOverflow; -// Access to decoderplan members needed by the decoder. +/* Access to decoderplan members needed by the decoder. */ const char *upb_pbdecoder_getopname(unsigned int op); -// JIT codegen entry point. +/* JIT codegen entry point. */ void upb_pbdecoder_jit(mgroup *group); void upb_pbdecoder_freejit(mgroup *group); +UPB_REFCOUNTED_CMETHODS(mgroup, mgroup_upcast) -// A special label that means "do field dispatch for this message and branch to -// wherever that takes you." +/* A special label that means "do field dispatch for this message and branch to + * wherever that takes you." */ #define LABEL_DISPATCH 0 -// A special slot in the dispatch table that stores the epilogue (ENDMSG and/or -// RET) for branching to when we find an appropriate ENDGROUP tag. +/* A special slot in the dispatch table that stores the epilogue (ENDMSG and/or + * RET) for branching to when we find an appropriate ENDGROUP tag. */ #define DISPATCH_ENDMSG 0 -// It's important to use this invalid wire type instead of 0 (which is a valid -// wire type). +/* It's important to use this invalid wire type instead of 0 (which is a valid + * wire type). */ #define NO_WIRE_TYPE 0xff -// The dispatch table layout is: -// [field number] -> [ 48-bit offset ][ 8-bit wt2 ][ 8-bit wt1 ] -// -// If wt1 matches, jump to the 48-bit offset. If wt2 matches, lookup -// (UPB_MAX_FIELDNUMBER + fieldnum) and jump there. -// -// We need two wire types because of packed/non-packed compatibility. A -// primitive repeated field can use either wire type and be valid. While we -// could key the table on fieldnum+wiretype, the table would be 8x sparser. -// -// Storing two wire types in the primary value allows us to quickly rule out -// the second wire type without needing to do a separate lookup (this case is -// less common than an unknown field). +/* The dispatch table layout is: + * [field number] -> [ 48-bit offset ][ 8-bit wt2 ][ 8-bit wt1 ] + * + * If wt1 matches, jump to the 48-bit offset. If wt2 matches, lookup + * (UPB_MAX_FIELDNUMBER + fieldnum) and jump there. + * + * We need two wire types because of packed/non-packed compatibility. A + * primitive repeated field can use either wire type and be valid. While we + * could key the table on fieldnum+wiretype, the table would be 8x sparser. + * + * Storing two wire types in the primary value allows us to quickly rule out + * the second wire type without needing to do a separate lookup (this case is + * less common than an unknown field). */ UPB_INLINE uint64_t upb_pbdecoder_packdispatch(uint64_t ofs, uint8_t wt1, uint8_t wt2) { return (ofs << 16) | (wt2 << 8) | wt1; @@ -7516,20 +7687,20 @@ UPB_INLINE void upb_pbdecoder_unpackdispatch(uint64_t dispatch, uint64_t *ofs, *ofs = dispatch >> 16; } -// All of the functions in decoder.c that return int32_t return values according -// to the following scheme: -// 1. negative values indicate a return code from the following list. -// 2. positive values indicate that error or end of buffer was hit, and -// that the decode function should immediately return the given value -// (the decoder state has already been suspended and is ready to be -// resumed). +/* All of the functions in decoder.c that return int32_t return values according + * to the following scheme: + * 1. negative values indicate a return code from the following list. + * 2. positive values indicate that error or end of buffer was hit, and + * that the decode function should immediately return the given value + * (the decoder state has already been suspended and is ready to be + * resumed). */ #define DECODE_OK -1 -#define DECODE_MISMATCH -2 // Used only from checktag_slow(). -#define DECODE_ENDGROUP -3 // Used only from checkunknown(). +#define DECODE_MISMATCH -2 /* Used only from checktag_slow(). */ +#define DECODE_ENDGROUP -3 /* Used only from checkunknown(). */ #define CHECK_RETURN(x) { int32_t ret = x; if (ret >= 0) return ret; } -#endif // UPB_DECODER_INT_H_ +#endif /* UPB_DECODER_INT_H_ */ /* * upb - a minimalist implementation of protocol buffers. * @@ -7551,25 +7722,25 @@ UPB_INLINE void upb_pbdecoder_unpackdispatch(uint64_t dispatch, uint64_t *ofs, extern "C" { #endif -// A list of types as they are encoded on-the-wire. +/* A list of types as they are encoded on-the-wire. */ typedef enum { UPB_WIRE_TYPE_VARINT = 0, UPB_WIRE_TYPE_64BIT = 1, UPB_WIRE_TYPE_DELIMITED = 2, UPB_WIRE_TYPE_START_GROUP = 3, UPB_WIRE_TYPE_END_GROUP = 4, - UPB_WIRE_TYPE_32BIT = 5, + UPB_WIRE_TYPE_32BIT = 5 } upb_wiretype_t; #define UPB_MAX_WIRE_TYPE 5 -// The maximum number of bytes that it takes to encode a 64-bit varint. -// Note that with a better encoding this could be 9 (TODO: write up a -// wiki document about this). +/* The maximum number of bytes that it takes to encode a 64-bit varint. + * Note that with a better encoding this could be 9 (TODO: write up a + * wiki document about this). */ #define UPB_PB_VARINT_MAX_LEN 10 -// Array of the "native" (ie. non-packed-repeated) wire type for the given a -// descriptor type (upb_descriptortype_t). +/* Array of the "native" (ie. non-packed-repeated) wire type for the given a + * descriptor type (upb_descriptortype_t). */ extern const uint8_t upb_pb_native_wire_types[]; /* Zig-zag encoding/decoding **************************************************/ @@ -7585,44 +7756,59 @@ UPB_INLINE uint64_t upb_zzenc_64(int64_t n) { return (n << 1) ^ (n >> 63); } /* Decoding *******************************************************************/ -// All decoding functions return this struct by value. +/* All decoding functions return this struct by value. */ typedef struct { - const char *p; // NULL if the varint was unterminated. + const char *p; /* NULL if the varint was unterminated. */ uint64_t val; } upb_decoderet; -// Four functions for decoding a varint of at most eight bytes. They are all -// functionally identical, but are implemented in different ways and likely have -// different performance profiles. We keep them around for performance testing. -// -// Note that these functions may not read byte-by-byte, so they must not be used -// unless there are at least eight bytes left in the buffer! +UPB_INLINE upb_decoderet upb_decoderet_make(const char *p, uint64_t val) { + upb_decoderet ret; + ret.p = p; + ret.val = val; + return ret; +} + +/* Four functions for decoding a varint of at most eight bytes. They are all + * functionally identical, but are implemented in different ways and likely have + * different performance profiles. We keep them around for performance testing. + * + * Note that these functions may not read byte-by-byte, so they must not be used + * unless there are at least eight bytes left in the buffer! */ upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r); upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r); upb_decoderet upb_vdecode_max8_wright(upb_decoderet r); upb_decoderet upb_vdecode_max8_massimino(upb_decoderet r); -// Template for a function that checks the first two bytes with branching -// and dispatches 2-10 bytes with a separate function. Note that this may read -// up to 10 bytes, so it must not be used unless there are at least ten bytes -// left in the buffer! +/* Template for a function that checks the first two bytes with branching + * and dispatches 2-10 bytes with a separate function. Note that this may read + * up to 10 bytes, so it must not be used unless there are at least ten bytes + * left in the buffer! */ #define UPB_VARINT_DECODER_CHECK2(name, decode_max8_function) \ UPB_INLINE upb_decoderet upb_vdecode_check2_ ## name(const char *_p) { \ uint8_t *p = (uint8_t*)_p; \ - if ((*p & 0x80) == 0) { upb_decoderet r = {_p + 1, *p & 0x7fU}; return r; } \ - upb_decoderet r = {_p + 2, (*p & 0x7fU) | ((*(p + 1) & 0x7fU) << 7)}; \ - if ((*(p + 1) & 0x80) == 0) return r; \ + upb_decoderet r; \ + if ((*p & 0x80) == 0) { \ + /* Common case: one-byte varint. */ \ + return upb_decoderet_make(_p + 1, *p & 0x7fU); \ + } \ + r = upb_decoderet_make(_p + 2, (*p & 0x7fU) | ((*(p + 1) & 0x7fU) << 7)); \ + if ((*(p + 1) & 0x80) == 0) { \ + /* Two-byte varint. */ \ + return r; \ + } \ + /* Longer varint, fallback to out-of-line function. */ \ return decode_max8_function(r); \ } -UPB_VARINT_DECODER_CHECK2(branch32, upb_vdecode_max8_branch32); -UPB_VARINT_DECODER_CHECK2(branch64, upb_vdecode_max8_branch64); -UPB_VARINT_DECODER_CHECK2(wright, upb_vdecode_max8_wright); -UPB_VARINT_DECODER_CHECK2(massimino, upb_vdecode_max8_massimino); +UPB_VARINT_DECODER_CHECK2(branch32, upb_vdecode_max8_branch32) +UPB_VARINT_DECODER_CHECK2(branch64, upb_vdecode_max8_branch64) +UPB_VARINT_DECODER_CHECK2(wright, upb_vdecode_max8_wright) +UPB_VARINT_DECODER_CHECK2(massimino, upb_vdecode_max8_massimino) #undef UPB_VARINT_DECODER_CHECK2 -// Our canonical functions for decoding varints, based on the currently -// favored best-performing implementations. +/* Our canonical functions for decoding varints, based on the currently + * favored best-performing implementations. */ UPB_INLINE upb_decoderet upb_vdecode_fast(const char *p) { if (sizeof(long) == 8) return upb_vdecode_check2_branch64(p); @@ -7639,7 +7825,7 @@ UPB_INLINE upb_decoderet upb_vdecode_max8_fast(upb_decoderet r) { UPB_INLINE int upb_value_size(uint64_t val) { #ifdef __GNUC__ - int high_bit = 63 - __builtin_clzll(val); // 0-based, undef if val == 0. + int high_bit = 63 - __builtin_clzll(val); /* 0-based, undef if val == 0. */ #else int high_bit = 0; uint64_t tmp = val; @@ -7648,13 +7834,14 @@ UPB_INLINE int upb_value_size(uint64_t val) { return val == 0 ? 1 : high_bit / 8 + 1; } -// Encodes a 64-bit varint into buf (which must be >=UPB_PB_VARINT_MAX_LEN -// bytes long), returning how many bytes were used. -// -// TODO: benchmark and optimize if necessary. +/* Encodes a 64-bit varint into buf (which must be >=UPB_PB_VARINT_MAX_LEN + * bytes long), returning how many bytes were used. + * + * TODO: benchmark and optimize if necessary. */ UPB_INLINE size_t upb_vencode64(uint64_t val, char *buf) { + size_t i; if (val == 0) { buf[0] = 0; return 1; } - size_t i = 0; + i = 0; while (val) { uint8_t byte = val & 0x7fU; val >>= 7; @@ -7669,7 +7856,7 @@ UPB_INLINE size_t upb_varint_size(uint64_t val) { return upb_vencode64(val, buf); } -// Encodes a 32-bit varint, *not* sign-extended. +/* Encodes a 32-bit varint, *not* sign-extended. */ UPB_INLINE uint64_t upb_vencode32(uint32_t val) { char buf[UPB_PB_VARINT_MAX_LEN]; size_t bytes = upb_vencode64(val, buf); @@ -7707,41 +7894,41 @@ UPB_INLINE uint64_t upb_vencode32(uint32_t val) { namespace upb { namespace pb { class Encoder; -} // namespace pb -} // namespace upb +} /* namespace pb */ +} /* namespace upb */ #endif -UPB_DECLARE_TYPE(upb::pb::Encoder, upb_pb_encoder); +UPB_DECLARE_TYPE(upb::pb::Encoder, upb_pb_encoder) #define UPB_PBENCODER_MAX_NESTING 100 /* upb::pb::Encoder ***********************************************************/ -// Preallocation hint: decoder won't allocate more bytes than this when first -// constructed. This hint may be an overestimate for some build configurations. -// But if the decoder library is upgraded without recompiling the application, -// it may be an underestimate. +/* Preallocation hint: decoder won't allocate more bytes than this when first + * constructed. This hint may be an overestimate for some build configurations. + * But if the decoder library is upgraded without recompiling the application, + * it may be an underestimate. */ #define UPB_PB_ENCODER_SIZE 768 #ifdef __cplusplus class upb::pb::Encoder { public: - // Creates a new encoder in the given environment. The Handlers must have - // come from NewHandlers() below. + /* Creates a new encoder in the given environment. The Handlers must have + * come from NewHandlers() below. */ static Encoder* Create(Environment* env, const Handlers* handlers, BytesSink* output); - // The input to the encoder. + /* The input to the encoder. */ Sink* input(); - // Creates a new set of handlers for this MessageDef. + /* Creates a new set of handlers for this MessageDef. */ static reffed_ptr<const Handlers> NewHandlers(const MessageDef* msg); static const size_t kSize = UPB_PB_ENCODER_SIZE; private: - UPB_DISALLOW_POD_OPS(Encoder, upb::pb::Encoder); + UPB_DISALLOW_POD_OPS(Encoder, upb::pb::Encoder) }; #endif @@ -7772,8 +7959,8 @@ inline reffed_ptr<const Handlers> Encoder::NewHandlers( const Handlers* h = upb_pb_encoder_newhandlers(md, &h); return reffed_ptr<const Handlers>(h, &h); } -} // namespace pb -} // namespace upb +} /* namespace pb */ +} /* namespace upb */ #endif @@ -7812,23 +7999,23 @@ inline reffed_ptr<const Handlers> Encoder::NewHandlers( extern "C" { #endif -// Loads all defs from the given protobuf binary descriptor, setting default -// accessors and a default layout on all messages. The caller owns the -// returned array of defs, which will be of length *n. On error NULL is -// returned and status is set (if non-NULL). +/* Loads all defs from the given protobuf binary descriptor, setting default + * accessors and a default layout on all messages. The caller owns the + * returned array of defs, which will be of length *n. On error NULL is + * returned and status is set (if non-NULL). */ upb_def **upb_load_defs_from_descriptor(const char *str, size_t len, int *n, void *owner, upb_status *status); -// Like the previous but also adds the loaded defs to the given symtab. +/* Like the previous but also adds the loaded defs to the given symtab. */ bool upb_load_descriptor_into_symtab(upb_symtab *symtab, const char *str, size_t len, upb_status *status); -// Like the previous but also reads the descriptor from the given filename. +/* Like the previous but also reads the descriptor from the given filename. */ bool upb_load_descriptor_file_into_symtab(upb_symtab *symtab, const char *fname, upb_status *status); -// Reads the given filename into a character string, returning NULL if there -// was an error. +/* Reads the given filename into a character string, returning NULL if there + * was an error. */ char *upb_readfile(const char *filename, size_t *len); #ifdef __cplusplus @@ -7836,8 +8023,8 @@ char *upb_readfile(const char *filename, size_t *len); namespace upb { -// All routines that load descriptors expect the descriptor to be a -// FileDescriptorSet. +/* All routines that load descriptors expect the descriptor to be a + * FileDescriptorSet. */ inline bool LoadDescriptorFileIntoSymtab(SymbolTable* s, const char *fname, Status* status) { return upb_load_descriptor_file_into_symtab(s, fname, status); @@ -7848,17 +8035,17 @@ inline bool LoadDescriptorIntoSymtab(SymbolTable* s, const char* str, return upb_load_descriptor_into_symtab(s, str, len, status); } -// Templated so it can accept both string and std::string. +/* Templated so it can accept both string and std::string. */ template <typename T> bool LoadDescriptorIntoSymtab(SymbolTable* s, const T& desc, Status* status) { return upb_load_descriptor_into_symtab(s, desc.c_str(), desc.size(), status); } -} // namespace upb +} /* namespace upb */ #endif -#endif +#endif /* UPB_GLUE_H */ /* * upb - a minimalist implementation of protocol buffers. * @@ -7874,18 +8061,18 @@ bool LoadDescriptorIntoSymtab(SymbolTable* s, const T& desc, Status* status) { namespace upb { namespace pb { class TextPrinter; -} // namespace pb -} // namespace upb +} /* namespace pb */ +} /* namespace upb */ #endif -UPB_DECLARE_TYPE(upb::pb::TextPrinter, upb_textprinter); +UPB_DECLARE_TYPE(upb::pb::TextPrinter, upb_textprinter) #ifdef __cplusplus class upb::pb::TextPrinter { public: - // The given handlers must have come from NewHandlers(). It must outlive the - // TextPrinter. + /* The given handlers must have come from NewHandlers(). It must outlive the + * TextPrinter. */ static TextPrinter *Create(Environment *env, const upb::Handlers *handlers, BytesSink *output); @@ -7893,8 +8080,8 @@ class upb::pb::TextPrinter { Sink* input(); - // If handler caching becomes a requirement we can add a code cache as in - // decoder.h + /* If handler caching becomes a requirement we can add a code cache as in + * decoder.h */ static reffed_ptr<const Handlers> NewHandlers(const MessageDef* md); }; @@ -7902,7 +8089,7 @@ class upb::pb::TextPrinter { UPB_BEGIN_EXTERN_C -// C API. +/* C API. */ upb_textprinter *upb_textprinter_create(upb_env *env, const upb_handlers *h, upb_bytessink *output); void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line); @@ -7933,8 +8120,8 @@ inline reffed_ptr<const Handlers> TextPrinter::NewHandlers( const Handlers* h = upb_textprinter_newhandlers(md, &h); return reffed_ptr<const Handlers>(h, &h); } -} // namespace pb -} // namespace upb +} /* namespace pb */ +} /* namespace upb */ #endif @@ -7957,23 +8144,24 @@ inline reffed_ptr<const Handlers> TextPrinter::NewHandlers( namespace upb { namespace json { class Parser; -} // namespace json -} // namespace upb +} /* namespace json */ +} /* namespace upb */ #endif -UPB_DECLARE_TYPE(upb::json::Parser, upb_json_parser); +UPB_DECLARE_TYPE(upb::json::Parser, upb_json_parser) /* upb::json::Parser **********************************************************/ -// Preallocation hint: parser won't allocate more bytes than this when first -// constructed. This hint may be an overestimate for some build configurations. -// But if the parser library is upgraded without recompiling the application, -// it may be an underestimate. +/* Preallocation hint: parser won't allocate more bytes than this when first + * constructed. This hint may be an overestimate for some build configurations. + * But if the parser library is upgraded without recompiling the application, + * it may be an underestimate. */ #define UPB_JSON_PARSER_SIZE 3568 #ifdef __cplusplus -// Parses an incoming BytesStream, pushing the results to the destination sink. +/* Parses an incoming BytesStream, pushing the results to the destination + * sink. */ class upb::json::Parser { public: static Parser* Create(Environment* env, Sink* output); @@ -7981,7 +8169,7 @@ class upb::json::Parser { BytesSink* input(); private: - UPB_DISALLOW_POD_OPS(Parser, upb::json::Parser); + UPB_DISALLOW_POD_OPS(Parser, upb::json::Parser) }; #endif @@ -8003,13 +8191,13 @@ inline Parser* Parser::Create(Environment* env, Sink* output) { inline BytesSink* Parser::input() { return upb_json_parser_input(this); } -} // namespace json -} // namespace upb +} /* namespace json */ +} /* namespace upb */ #endif -#endif // UPB_JSON_PARSER_H_ +#endif /* UPB_JSON_PARSER_H_ */ /* * upb - a minimalist implementation of protocol buffers. * @@ -8028,11 +8216,11 @@ inline BytesSink* Parser::input() { namespace upb { namespace json { class Printer; -} // namespace json -} // namespace upb +} /* namespace json */ +} /* namespace upb */ #endif -UPB_DECLARE_TYPE(upb::json::Printer, upb_json_printer); +UPB_DECLARE_TYPE(upb::json::Printer, upb_json_printer) /* upb::json::Printer *********************************************************/ @@ -8041,29 +8229,29 @@ UPB_DECLARE_TYPE(upb::json::Printer, upb_json_printer); #ifdef __cplusplus -// Prints an incoming stream of data to a BytesSink in JSON format. +/* Prints an incoming stream of data to a BytesSink in JSON format. */ class upb::json::Printer { public: static Printer* Create(Environment* env, const upb::Handlers* handlers, BytesSink* output); - // The input to the printer. + /* The input to the printer. */ Sink* input(); - // Returns handlers for printing according to the specified schema. + /* Returns handlers for printing according to the specified schema. */ static reffed_ptr<const Handlers> NewHandlers(const upb::MessageDef* md); static const size_t kSize = UPB_JSON_PRINTER_SIZE; private: - UPB_DISALLOW_POD_OPS(Printer, upb::json::Printer); + UPB_DISALLOW_POD_OPS(Printer, upb::json::Printer) }; #endif UPB_BEGIN_EXTERN_C -// Native C API. +/* Native C API. */ upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h, upb_bytessink *output); upb_sink *upb_json_printer_input(upb_json_printer *p); @@ -8086,9 +8274,9 @@ inline reffed_ptr<const Handlers> Printer::NewHandlers( const Handlers* h = upb_json_printer_newhandlers(md, &h); return reffed_ptr<const Handlers>(h, &h); } -} // namespace json -} // namespace upb +} /* namespace json */ +} /* namespace upb */ #endif -#endif // UPB_JSON_TYPED_PRINTER_H_ +#endif /* UPB_JSON_TYPED_PRINTER_H_ */ diff --git a/src/Makefile.am b/src/Makefile.am index 33894dc1..5b28579f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,17 +4,25 @@ if HAVE_ZLIB GZCHECKPROGRAMS = zcgzip zcgunzip GZHEADERS = google/protobuf/io/gzip_stream.h GZTESTS = google/protobuf/io/gzip_stream_unittest.sh +ZLIB_DEF = -DHAVE_ZLIB=1 else GZCHECKPROGRAMS = GZHEADERS = GZTESTS = +ZLIB_DEF = +endif + +if HAVE_PTHREAD +PTHREAD_DEF = -DHAVE_PTHREAD=1 +else +PTHREAD_DEF = endif if GCC # These are good warnings to turn on by default -NO_OPT_CXXFLAGS = $(PTHREAD_CFLAGS) -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare +NO_OPT_CXXFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_DEF) $(ZLIB_DEF) -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare else -NO_OPT_CXXFLAGS = $(PTHREAD_CFLAGS) +NO_OPT_CXXFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_DEF) $(ZLIB_DEF) endif AM_CXXFLAGS = $(NO_OPT_CXXFLAGS) $(PROTOBUF_OPT_FLAG) @@ -41,24 +49,12 @@ nobase_dist_proto_DATA = google/protobuf/descriptor.proto \ clean-local: rm -f *.loT -public_config = google/protobuf/stubs/pbconfig.h - -CLEANFILES = $(protoc_outputs) $(public_config) unittest_proto_middleman \ +CLEANFILES = $(protoc_outputs) unittest_proto_middleman \ testzip.jar testzip.list testzip.proto testzip.zip MAINTAINERCLEANFILES = \ Makefile.in -# Generate and distribute a minimum config.h file to make hash_map work. -# The autoheader config has too much info, which might conflict with other -# macros applications might include. Thus, we create a stubs/pbconfig.h, that -# only #defines what we really need, and prefix it with GOOGLE_PROTOBUF_ to -# avoid conflicts. -$(public_config): $(top_builddir)/config.h $(top_srcdir)/config.h.include - echo "// Note: Google Protobuf internal only. Do NOT include." > $@ - cat $(top_builddir)/config.h | grep -f $(top_srcdir)/config.h.include | \ - sed 's,#define , #define GOOGLE_PROTOBUF_,' >> $@ - nobase_include_HEADERS = \ google/protobuf/stubs/atomic_sequence_num.h \ google/protobuf/stubs/atomicops.h \ @@ -80,6 +76,7 @@ nobase_include_HEADERS = \ google/protobuf/stubs/fastmem.h \ google/protobuf/stubs/hash.h \ google/protobuf/stubs/once.h \ + google/protobuf/stubs/pbconfig.h \ google/protobuf/stubs/platform_macros.h \ google/protobuf/stubs/shared_ptr.h \ google/protobuf/stubs/singleton.h \ @@ -147,13 +144,15 @@ nobase_include_HEADERS = \ google/protobuf/compiler/java/java_names.h \ google/protobuf/compiler/javanano/javanano_generator.h \ google/protobuf/compiler/objectivec/objectivec_generator.h \ - google/protobuf/compiler/objectivec/objectivec_helpers.h \ + google/protobuf/compiler/objectivec/objectivec_helpers.h \ google/protobuf/compiler/python/python_generator.h \ google/protobuf/compiler/ruby/ruby_generator.h \ - google/protobuf/compiler/csharp/csharp_generator.h - -nobase_nodist_include_HEADERS = \ - $(public_config) + google/protobuf/compiler/csharp/csharp_generator.h \ + google/protobuf/util/type_resolver.h \ + google/protobuf/util/type_resolver_util.h \ + google/protobuf/util/json_util.h \ + google/protobuf/util/field_comparator.h \ + google/protobuf/util/message_differencer.h lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la @@ -162,13 +161,27 @@ libprotobuf_lite_la_LDFLAGS = -version-info 10:0:0 -export-dynamic -no-undefined libprotobuf_lite_la_SOURCES = \ google/protobuf/stubs/atomicops_internals_x86_gcc.cc \ google/protobuf/stubs/atomicops_internals_x86_msvc.cc \ + google/protobuf/stubs/bytestream.cc \ + google/protobuf/stubs/bytestream.h \ google/protobuf/stubs/common.cc \ - google/protobuf/stubs/once.cc \ google/protobuf/stubs/hash.h \ google/protobuf/stubs/map_util.h \ + google/protobuf/stubs/mathutil.h \ + google/protobuf/stubs/once.cc \ google/protobuf/stubs/shared_ptr.h \ + google/protobuf/stubs/status.cc \ + google/protobuf/stubs/status.h \ + google/protobuf/stubs/status_macros.h \ + google/protobuf/stubs/statusor.cc \ + google/protobuf/stubs/statusor.h \ + google/protobuf/stubs/stringpiece.cc \ + google/protobuf/stubs/stringpiece.h \ google/protobuf/stubs/stringprintf.cc \ google/protobuf/stubs/stringprintf.h \ + google/protobuf/stubs/strutil.cc \ + google/protobuf/stubs/strutil.h \ + google/protobuf/stubs/time.cc \ + google/protobuf/stubs/time.h \ google/protobuf/arena.cc \ google/protobuf/arenastring.cc \ google/protobuf/extension_set.cc \ @@ -180,7 +193,6 @@ libprotobuf_lite_la_SOURCES = \ google/protobuf/io/coded_stream_inl.h \ google/protobuf/io/zero_copy_stream.cc \ google/protobuf/io/zero_copy_stream_impl_lite.cc -nodist_libprotobuf_lite_la_SOURCES = $(public_config) libprotobuf_la_LIBADD = $(PTHREAD_LIBS) libprotobuf_la_LDFLAGS = -version-info 10:0:0 -export-dynamic -no-undefined @@ -188,6 +200,8 @@ libprotobuf_la_SOURCES = \ $(libprotobuf_lite_la_SOURCES) \ google/protobuf/any.pb.cc \ google/protobuf/api.pb.cc \ + google/protobuf/stubs/mathlimits.h \ + google/protobuf/stubs/mathlimits.cc \ google/protobuf/any.cc \ google/protobuf/descriptor.cc \ google/protobuf/descriptor_database.cc \ @@ -206,8 +220,6 @@ libprotobuf_la_SOURCES = \ google/protobuf/source_context.pb.cc \ google/protobuf/struct.pb.cc \ google/protobuf/stubs/structurally_valid.cc \ - google/protobuf/stubs/strutil.cc \ - google/protobuf/stubs/strutil.h \ google/protobuf/stubs/substitute.cc \ google/protobuf/stubs/substitute.h \ google/protobuf/text_format.cc \ @@ -222,7 +234,46 @@ libprotobuf_la_SOURCES = \ google/protobuf/io/tokenizer.cc \ google/protobuf/io/zero_copy_stream_impl.cc \ google/protobuf/compiler/importer.cc \ - google/protobuf/compiler/parser.cc + google/protobuf/compiler/parser.cc \ + google/protobuf/util/field_comparator.cc \ + google/protobuf/util/internal/constants.h \ + google/protobuf/util/internal/datapiece.cc \ + google/protobuf/util/internal/datapiece.h \ + google/protobuf/util/internal/default_value_objectwriter.cc \ + google/protobuf/util/internal/default_value_objectwriter.h \ + google/protobuf/util/internal/error_listener.cc \ + google/protobuf/util/internal/error_listener.h \ + google/protobuf/util/internal/expecting_objectwriter.h \ + google/protobuf/util/internal/field_mask_utility.cc \ + google/protobuf/util/internal/field_mask_utility.h \ + google/protobuf/util/internal/json_escaping.cc \ + google/protobuf/util/internal/json_escaping.h \ + google/protobuf/util/internal/json_objectwriter.cc \ + google/protobuf/util/internal/json_objectwriter.h \ + google/protobuf/util/internal/json_stream_parser.cc \ + google/protobuf/util/internal/json_stream_parser.h \ + google/protobuf/util/internal/location_tracker.h \ + google/protobuf/util/internal/mock_error_listener.h \ + google/protobuf/util/internal/object_location_tracker.h \ + google/protobuf/util/internal/object_source.h \ + google/protobuf/util/internal/object_writer.cc \ + google/protobuf/util/internal/object_writer.h \ + google/protobuf/util/internal/protostream_objectsource.cc \ + google/protobuf/util/internal/protostream_objectsource.h \ + google/protobuf/util/internal/protostream_objectwriter.cc \ + google/protobuf/util/internal/protostream_objectwriter.h \ + google/protobuf/util/internal/snake2camel_objectwriter.h \ + google/protobuf/util/internal/structured_objectwriter.h \ + google/protobuf/util/internal/testdata \ + google/protobuf/util/internal/type_info.cc \ + google/protobuf/util/internal/type_info.h \ + google/protobuf/util/internal/type_info_test_helper.cc \ + google/protobuf/util/internal/type_info_test_helper.h \ + google/protobuf/util/internal/utility.cc \ + google/protobuf/util/internal/utility.h \ + google/protobuf/util/json_util.cc \ + google/protobuf/util/type_resolver_util.cc \ + google/protobuf/util/message_differencer.cc nodist_libprotobuf_la_SOURCES = $(nodist_libprotobuf_lite_la_SOURCES) libprotoc_la_LIBADD = $(PTHREAD_LIBS) libprotobuf.la @@ -401,34 +452,44 @@ protoc_SOURCES = google/protobuf/compiler/main.cc # Tests ============================================================== -protoc_inputs = \ - google/protobuf/any_test.proto \ - google/protobuf/map_lite_unittest.proto \ - google/protobuf/map_proto2_unittest.proto \ - google/protobuf/map_unittest.proto \ - google/protobuf/unittest.proto \ - google/protobuf/unittest_arena.proto \ - google/protobuf/unittest_custom_options.proto \ - google/protobuf/unittest_drop_unknown_fields.proto \ - google/protobuf/unittest_embed_optimize_for.proto \ - google/protobuf/unittest_empty.proto \ - google/protobuf/unittest_import_lite.proto \ - google/protobuf/unittest_import.proto \ - google/protobuf/unittest_import_public_lite.proto \ - google/protobuf/unittest_import_public.proto \ - google/protobuf/unittest_lite_imports_nonlite.proto \ - google/protobuf/unittest_lite.proto \ - google/protobuf/unittest_mset.proto \ - google/protobuf/unittest_no_arena_import.proto \ - google/protobuf/unittest_no_arena.proto \ - google/protobuf/unittest_no_field_presence.proto \ - google/protobuf/unittest_no_generic_services.proto \ - google/protobuf/unittest_optimize_for.proto \ - google/protobuf/unittest_preserve_unknown_enum.proto \ - google/protobuf/unittest_preserve_unknown_enum2.proto \ - google/protobuf/unittest_proto3_arena.proto \ - google/protobuf/unittest_well_known_types.proto \ - google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto \ +protoc_inputs = \ + google/protobuf/any_test.proto \ + google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto \ + google/protobuf/map_lite_unittest.proto \ + google/protobuf/map_proto2_unittest.proto \ + google/protobuf/map_unittest.proto \ + google/protobuf/unittest_arena.proto \ + google/protobuf/unittest_custom_options.proto \ + google/protobuf/unittest_drop_unknown_fields.proto \ + google/protobuf/unittest_embed_optimize_for.proto \ + google/protobuf/unittest_empty.proto \ + google/protobuf/unittest_enormous_descriptor.proto \ + google/protobuf/unittest_import_lite.proto \ + google/protobuf/unittest_import.proto \ + google/protobuf/unittest_import_public_lite.proto \ + google/protobuf/unittest_import_public.proto \ + google/protobuf/unittest_lite_imports_nonlite.proto \ + google/protobuf/unittest_lite.proto \ + google/protobuf/unittest_mset.proto \ + google/protobuf/unittest_no_arena_import.proto \ + google/protobuf/unittest_no_arena.proto \ + google/protobuf/unittest_no_field_presence.proto \ + google/protobuf/unittest_no_generic_services.proto \ + google/protobuf/unittest_optimize_for.proto \ + google/protobuf/unittest_preserve_unknown_enum2.proto \ + google/protobuf/unittest_preserve_unknown_enum.proto \ + google/protobuf/unittest.proto \ + google/protobuf/unittest_proto3_arena.proto \ + google/protobuf/unittest_well_known_types.proto \ + google/protobuf/util/internal/testdata/anys.proto \ + google/protobuf/util/internal/testdata/books.proto \ + google/protobuf/util/internal/testdata/default_value.proto \ + google/protobuf/util/internal/testdata/default_value_test.proto \ + google/protobuf/util/internal/testdata/field_mask.proto \ + google/protobuf/util/internal/testdata/maps.proto \ + google/protobuf/util/internal/testdata/struct.proto \ + google/protobuf/util/internal/testdata/timestamp_duration.proto \ + google/protobuf/util/json_format_proto3.proto \ google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto EXTRA_DIST = \ @@ -453,8 +514,7 @@ EXTRA_DIST = \ google/protobuf/compiler/ruby/ruby_generated_code.proto \ google/protobuf/compiler/ruby/ruby_generated_code.rb \ google/protobuf/compiler/package_info.h \ - google/protobuf/compiler/zip_output_unittest.sh \ - google/protobuf/unittest_enormous_descriptor.proto + google/protobuf/compiler/zip_output_unittest.sh protoc_lite_outputs = \ google/protobuf/map_lite_unittest.pb.cc \ @@ -466,58 +526,78 @@ protoc_lite_outputs = \ google/protobuf/unittest_import_public_lite.pb.cc \ google/protobuf/unittest_import_public_lite.pb.h -protoc_outputs = \ - $(protoc_lite_outputs) \ - google/protobuf/any_test.pb.cc \ - google/protobuf/any_test.pb.h \ - google/protobuf/map_proto2_unittest.pb.cc \ - google/protobuf/map_proto2_unittest.pb.h \ - google/protobuf/map_unittest.pb.cc \ - google/protobuf/map_unittest.pb.h \ - google/protobuf/unittest.pb.cc \ - google/protobuf/unittest.pb.h \ - google/protobuf/unittest_arena.pb.cc \ - google/protobuf/unittest_arena.pb.h \ - google/protobuf/unittest_custom_options.pb.cc \ - google/protobuf/unittest_custom_options.pb.h \ - google/protobuf/unittest_drop_unknown_fields.pb.cc \ - google/protobuf/unittest_drop_unknown_fields.pb.h \ - google/protobuf/unittest_embed_optimize_for.pb.cc \ - google/protobuf/unittest_embed_optimize_for.pb.h \ - google/protobuf/unittest_empty.pb.cc \ - google/protobuf/unittest_empty.pb.h \ - google/protobuf/unittest_import.pb.cc \ - google/protobuf/unittest_import.pb.h \ - google/protobuf/unittest_import_public.pb.cc \ - google/protobuf/unittest_import_public.pb.h \ - google/protobuf/unittest_lite_imports_nonlite.pb.cc \ - google/protobuf/unittest_lite_imports_nonlite.pb.h \ - google/protobuf/unittest_mset.pb.cc \ - google/protobuf/unittest_mset.pb.h \ - google/protobuf/unittest_no_arena.pb.cc \ - google/protobuf/unittest_no_arena.pb.h \ - google/protobuf/unittest_no_arena_import.pb.cc \ - google/protobuf/unittest_no_arena_import.pb.h \ - google/protobuf/unittest_no_field_presence.pb.cc \ - google/protobuf/unittest_no_field_presence.pb.h \ - google/protobuf/unittest_no_generic_services.pb.cc \ - google/protobuf/unittest_no_generic_services.pb.h \ - google/protobuf/unittest_optimize_for.pb.cc \ - google/protobuf/unittest_optimize_for.pb.h \ - google/protobuf/unittest_preserve_unknown_enum.pb.cc \ - google/protobuf/unittest_preserve_unknown_enum.pb.h \ - google/protobuf/unittest_preserve_unknown_enum2.pb.cc \ - google/protobuf/unittest_preserve_unknown_enum2.pb.h \ - google/protobuf/unittest_proto3_arena.pb.cc \ - google/protobuf/unittest_proto3_arena.pb.h \ - google/protobuf/unittest_well_known_types.pb.cc \ - google/protobuf/unittest_well_known_types.pb.h \ - google/protobuf/compiler/cpp/cpp_test_large_enum_value.pb.cc \ - google/protobuf/compiler/cpp/cpp_test_large_enum_value.pb.h \ - google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc \ - google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h - -BUILT_SOURCES = $(public_config) $(protoc_outputs) +protoc_outputs = \ + $(protoc_lite_outputs) \ + google/protobuf/any_test.pb.cc \ + google/protobuf/any_test.pb.h \ + google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc \ + google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h \ + google/protobuf/compiler/cpp/cpp_test_large_enum_value.pb.cc \ + google/protobuf/compiler/cpp/cpp_test_large_enum_value.pb.h \ + google/protobuf/map_proto2_unittest.pb.cc \ + google/protobuf/map_proto2_unittest.pb.h \ + google/protobuf/map_unittest.pb.cc \ + google/protobuf/map_unittest.pb.h \ + google/protobuf/unittest_arena.pb.cc \ + google/protobuf/unittest_arena.pb.h \ + google/protobuf/unittest_custom_options.pb.cc \ + google/protobuf/unittest_custom_options.pb.h \ + google/protobuf/unittest_drop_unknown_fields.pb.cc \ + google/protobuf/unittest_drop_unknown_fields.pb.h \ + google/protobuf/unittest_embed_optimize_for.pb.cc \ + google/protobuf/unittest_embed_optimize_for.pb.h \ + google/protobuf/unittest_empty.pb.cc \ + google/protobuf/unittest_empty.pb.h \ + google/protobuf/unittest_enormous_descriptor.pb.cc \ + google/protobuf/unittest_enormous_descriptor.pb.h \ + google/protobuf/unittest_import.pb.cc \ + google/protobuf/unittest_import.pb.h \ + google/protobuf/unittest_import_public.pb.cc \ + google/protobuf/unittest_import_public.pb.h \ + google/protobuf/unittest_lite_imports_nonlite.pb.cc \ + google/protobuf/unittest_lite_imports_nonlite.pb.h \ + google/protobuf/unittest_mset.pb.cc \ + google/protobuf/unittest_mset.pb.h \ + google/protobuf/unittest_no_arena_import.pb.cc \ + google/protobuf/unittest_no_arena_import.pb.h \ + google/protobuf/unittest_no_arena.pb.cc \ + google/protobuf/unittest_no_arena.pb.h \ + google/protobuf/unittest_no_field_presence.pb.cc \ + google/protobuf/unittest_no_field_presence.pb.h \ + google/protobuf/unittest_no_generic_services.pb.cc \ + google/protobuf/unittest_no_generic_services.pb.h \ + google/protobuf/unittest_optimize_for.pb.cc \ + google/protobuf/unittest_optimize_for.pb.h \ + google/protobuf/unittest.pb.cc \ + google/protobuf/unittest.pb.h \ + google/protobuf/unittest_preserve_unknown_enum2.pb.cc \ + google/protobuf/unittest_preserve_unknown_enum2.pb.h \ + google/protobuf/unittest_preserve_unknown_enum.pb.cc \ + google/protobuf/unittest_preserve_unknown_enum.pb.h \ + google/protobuf/unittest_proto3_arena.pb.cc \ + google/protobuf/unittest_proto3_arena.pb.h \ + google/protobuf/unittest_well_known_types.pb.cc \ + google/protobuf/unittest_well_known_types.pb.h \ + google/protobuf/util/internal/testdata/anys.pb.cc \ + google/protobuf/util/internal/testdata/anys.pb.h \ + google/protobuf/util/internal/testdata/books.pb.cc \ + google/protobuf/util/internal/testdata/books.pb.h \ + google/protobuf/util/internal/testdata/default_value.pb.cc \ + google/protobuf/util/internal/testdata/default_value.pb.h \ + google/protobuf/util/internal/testdata/default_value_test.pb.cc \ + google/protobuf/util/internal/testdata/default_value_test.pb.h \ + google/protobuf/util/internal/testdata/field_mask.pb.cc \ + google/protobuf/util/internal/testdata/field_mask.pb.h \ + google/protobuf/util/internal/testdata/maps.pb.cc \ + google/protobuf/util/internal/testdata/maps.pb.h \ + google/protobuf/util/internal/testdata/struct.pb.cc \ + google/protobuf/util/internal/testdata/struct.pb.h \ + google/protobuf/util/internal/testdata/timestamp_duration.pb.cc \ + google/protobuf/util/internal/testdata/timestamp_duration.pb.h \ + google/protobuf/util/json_format_proto3.pb.cc \ + google/protobuf/util/json_format_proto3.pb.h + +BUILT_SOURCES = $(protoc_outputs) if USE_EXTERNAL_PROTOC @@ -554,21 +634,27 @@ COMMON_TEST_SOURCES = \ check_PROGRAMS = protoc protobuf-test protobuf-lazy-descriptor-test \ protobuf-lite-test test_plugin $(GZCHECKPROGRAMS) protobuf_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \ - $(top_builddir)/gtest/lib/libgtest.la \ - $(top_builddir)/gtest/lib/libgtest_main.la -protobuf_test_CPPFLAGS = -I$(top_srcdir)/gtest/include \ - -I$(top_builddir)/gtest/include + ../gmock/gtest/lib/libgtest.la \ + ../gmock/lib/libgmock.la \ + ../gmock/lib/libgmock_main.la +protobuf_test_CPPFLAGS = -I$(srcdir)/../gmock/gtest/include \ + -I$(srcdir)/../gmock/include # Disable optimization for tests unless the user explicitly asked for it, # since test_util.cc takes forever to compile with optimization (with GCC). # See configure.ac for more info. protobuf_test_CXXFLAGS = $(NO_OPT_CXXFLAGS) protobuf_test_SOURCES = \ + google/protobuf/stubs/bytestream_unittest.cc \ google/protobuf/stubs/common_unittest.cc \ google/protobuf/stubs/once_unittest.cc \ - google/protobuf/stubs/strutil_unittest.cc \ - google/protobuf/stubs/structurally_valid_unittest.cc \ + google/protobuf/stubs/statusor_test.cc \ + google/protobuf/stubs/status_test.cc \ + google/protobuf/stubs/stringpiece_unittest.cc \ google/protobuf/stubs/stringprintf_unittest.cc \ + google/protobuf/stubs/structurally_valid_unittest.cc \ + google/protobuf/stubs/strutil_unittest.cc \ google/protobuf/stubs/template_util_unittest.cc \ + google/protobuf/stubs/time_test.cc \ google/protobuf/stubs/type_traits_unittest.cc \ google/protobuf/any_test.cc \ google/protobuf/arenastring_unittest.cc \ @@ -611,16 +697,28 @@ protobuf_test_SOURCES = \ google/protobuf/compiler/python/python_plugin_unittest.cc \ google/protobuf/compiler/ruby/ruby_generator_unittest.cc \ google/protobuf/compiler/csharp/csharp_generator_unittest.cc \ + google/protobuf/util/field_comparator_test.cc \ + google/protobuf/util/internal/default_value_objectwriter_test.cc \ + google/protobuf/util/internal/json_objectwriter_test.cc \ + google/protobuf/util/internal/json_stream_parser_test.cc \ + google/protobuf/util/internal/protostream_objectsource_test.cc \ + google/protobuf/util/internal/protostream_objectwriter_test.cc \ + google/protobuf/util/internal/type_info_test_helper.cc \ + google/protobuf/util/json_util_test.cc \ + google/protobuf/util/type_resolver_util_test.cc \ $(COMMON_TEST_SOURCES) + + nodist_protobuf_test_SOURCES = $(protoc_outputs) # Run cpp_unittest again with PROTOBUF_TEST_NO_DESCRIPTORS defined. protobuf_lazy_descriptor_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la \ libprotoc.la \ - $(top_builddir)/gtest/lib/libgtest.la \ - $(top_builddir)/gtest/lib/libgtest_main.la -protobuf_lazy_descriptor_test_CPPFLAGS = -I$(top_srcdir)/gtest/include \ - -I$(top_builddir)/gtest/include \ + ../gmock/gtest/lib/libgtest.la \ + ../gmock/lib/libgmock.la \ + ../gmock/lib/libgmock_main.la +protobuf_lazy_descriptor_test_CPPFLAGS = -I$(srcdir)/../gmock/include \ + -I$(srcdir)/../gmock/gtest/include \ -DPROTOBUF_TEST_NO_DESCRIPTORS protobuf_lazy_descriptor_test_CXXFLAGS = $(NO_OPT_CXXFLAGS) protobuf_lazy_descriptor_test_SOURCES = \ @@ -645,9 +743,8 @@ nodist_protobuf_lite_test_SOURCES = $(protoc_lite_outputs) # Test plugin binary. test_plugin_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \ - $(top_builddir)/gtest/lib/libgtest.la -test_plugin_CPPFLAGS = -I$(top_srcdir)/gtest/include \ - -I$(top_builddir)/gtest/include + ../gmock/gtest/lib/libgtest.la +test_plugin_CPPFLAGS = -I$(srcdir)/../gmock/gtest/include test_plugin_SOURCES = \ google/protobuf/compiler/mock_code_generator.cc \ google/protobuf/testing/file.cc \ diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc index 96009645..ed1c5ef2 100755 --- a/src/google/protobuf/arena.cc +++ b/src/google/protobuf/arena.cc @@ -43,7 +43,7 @@ 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) +#elif defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) Arena::ThreadCache& Arena::thread_cache() { static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ = new internal::ThreadLocalStorage<ThreadCache>(); diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index 6c3f606e..51149bae 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h @@ -39,6 +39,7 @@ #include <google/protobuf/stubs/atomic_sequence_num.h> #include <google/protobuf/stubs/atomicops.h> #include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/platform_macros.h> #include <google/protobuf/stubs/type_traits.h> namespace google { @@ -528,7 +529,7 @@ 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) +#elif defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) // Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread // local storage class we implemented. // iOS also does not support the GOOGLE_THREAD_LOCAL keyword. diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 667b2b63..c57cfd3d 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -53,6 +53,10 @@ #include <google/protobuf/stubs/shared_ptr.h> #endif +#ifdef __APPLE__ +#include <mach-o/dyld.h> +#endif + #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/stringprintf.h> #include <google/protobuf/compiler/importer.h> @@ -186,6 +190,16 @@ bool GetProtocAbsolutePath(string* path) { #ifdef _WIN32 char buffer[MAX_PATH]; int len = GetModuleFileName(NULL, buffer, MAX_PATH); +#elif __APPLE__ + char buffer[PATH_MAX]; + int len = 0; + + char dirtybuffer[PATH_MAX]; + uint32_t size = sizeof(dirtybuffer); + if (_NSGetExecutablePath(dirtybuffer, &size) == 0) { + realpath(dirtybuffer, buffer); + len = strlen(buffer); + } #else char buffer[PATH_MAX]; int len = readlink("/proc/self/exe", buffer, PATH_MAX); diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index b997a51a..1f0a8205 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -434,20 +434,52 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { string file_data; file_proto.SerializeToString(&file_data); - printer->Print( - "::google::protobuf::DescriptorPool::InternalAddGeneratedFile("); - - // Only write 40 bytes per line. - static const int kBytesPerLine = 40; - for (int i = 0; i < file_data.size(); i += kBytesPerLine) { - printer->Print("\n \"$data$\"", - "data", - EscapeTrigraphs( - CEscape(file_data.substr(i, kBytesPerLine)))); + // Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535 + // bytes in length". Declare a static array of characters rather than use a + // string literal. + if (file_data.size() > 65535) { + printer->Print( + "static const char descriptor[] = {\n"); + printer->Indent(); + + // Only write 25 bytes per line. + static const int kBytesPerLine = 25; + for (int i = 0; i < file_data.size();) { + for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) { + printer->Print( + "$char$, ", + "char", SimpleItoa(file_data[i])); + } + printer->Print( + "\n"); + } + + printer->Outdent(); + printer->Print( + "};\n"); + + printer->Print( + "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n", + "size", SimpleItoa(file_data.size())); + + } else { + + printer->Print( + "::google::protobuf::DescriptorPool::InternalAddGeneratedFile("); + + // Only write 40 bytes per line. + static const int kBytesPerLine = 40; + for (int i = 0; i < file_data.size(); i += kBytesPerLine) { + printer->Print("\n \"$data$\"", + "data", + EscapeTrigraphs( + CEscape(file_data.substr(i, kBytesPerLine)))); + } + printer->Print( + ", $size$);\n", + "size", SimpleItoa(file_data.size())); + } - printer->Print( - ", $size$);\n", - "size", SimpleItoa(file_data.size())); // Call MessageFactory::InternalRegisterGeneratedFile(). printer->Print( diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index 212fe2e1..17f67a7b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -621,7 +621,7 @@ GenerateSingularFieldHasBits(const FieldDescriptor* field, // has_$name$() methods. vars["has_array_index"] = SimpleItoa(field->index() / 32); vars["has_mask"] = StrCat(strings::Hex(1u << (field->index() % 32), - strings::Hex::ZERO_PAD_8)); + strings::ZERO_PAD_8)); printer->Print(vars, "$inline$" "bool $classname$::has_$name$() const {\n" @@ -3364,7 +3364,7 @@ static string ConditionalToCheckBitmasks(const vector<uint32>& masks) { vector<string> parts; for (int i = 0; i < masks.size(); i++) { if (masks[i] == 0) continue; - string m = StrCat("0x", strings::Hex(masks[i], strings::Hex::ZERO_PAD_8)); + string m = StrCat("0x", strings::Hex(masks[i], strings::ZERO_PAD_8)); // Each xor evaluates to 0 if the expected bits are present. parts.push_back(StrCat("((_has_bits_[", i, "] & ", m, ") ^ ", m, ")")); } @@ -3510,7 +3510,7 @@ GenerateByteSize(io::Printer* printer) { } else { if (HasFieldPresence(descriptor_->file())) { printer->Print( - "if (_has_bits_[$index$ / 32] & $mask$) {\n", + "if (_has_bits_[$index$ / 32] & $mask$u) {\n", "index", SimpleItoa(i), "mask", SimpleItoa(mask)); printer->Indent(); @@ -3659,7 +3659,7 @@ GenerateIsInitialized(io::Printer* printer) { printer->Print( "if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n", "i", SimpleItoa(i), - "mask", StrCat(strings::Hex(mask, strings::Hex::ZERO_PAD_8))); + "mask", StrCat(strings::Hex(mask, strings::ZERO_PAD_8))); } } } diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index b11fb21a..bd1c0fde 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -55,6 +55,7 @@ #include <google/protobuf/unittest.pb.h> #include <google/protobuf/unittest_optimize_for.pb.h> #include <google/protobuf/unittest_embed_optimize_for.pb.h> +#include <google/protobuf/unittest_enormous_descriptor.pb.h> #include <google/protobuf/unittest_no_generic_services.pb.h> #include <google/protobuf/test_util.h> #include <google/protobuf/compiler/cpp/cpp_helpers.h> @@ -130,6 +131,17 @@ TEST(GeneratedDescriptorTest, IdenticalDescriptors) { generated_decsriptor_proto.DebugString()); } +// Test that generated code has proper descriptors: +// Touch a descriptor generated from an enormous message to validate special +// handling for descriptors exceeding the C++ standard's recommended minimum +// limit for string literal size +TEST(GeneratedDescriptorTest, EnormousDescriptor) { + const Descriptor* generated_descriptor = + TestEnormousDescriptor::descriptor(); + + EXPECT_TRUE(generated_descriptor != NULL); +} + #endif // !PROTOBUF_TEST_NO_DESCRIPTORS // =================================================================== diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.cc b/src/google/protobuf/compiler/csharp/csharp_enum.cc index 27643e61..0e8f9836 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum.cc @@ -40,7 +40,6 @@ #include <google/protobuf/compiler/csharp/csharp_enum.h> #include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_writer.h> using google::protobuf::internal::scoped_ptr; @@ -57,20 +56,20 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) : EnumGenerator::~EnumGenerator() { } -void EnumGenerator::Generate(Writer* writer) { - WriteGeneratedCodeAttributes(writer); - writer->WriteLine("$0$ enum $1$ {", - class_access_level(), - descriptor_->name()); - writer->Indent(); +void EnumGenerator::Generate(io::Printer* printer) { + WriteGeneratedCodeAttributes(printer); + printer->Print("$access_level$ enum $name$ {\n", + "access_level", class_access_level(), + "name", descriptor_->name()); + printer->Indent(); for (int i = 0; i < descriptor_->value_count(); i++) { - writer->WriteLine("$0$ = $1$,", - descriptor_->value(i)->name(), - SimpleItoa(descriptor_->value(i)->number())); + printer->Print("$name$ = $number$,\n", + "name", descriptor_->value(i)->name(), + "number", SimpleItoa(descriptor_->value(i)->number())); } - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.h b/src/google/protobuf/compiler/csharp/csharp_enum.h index eaa7a9c5..2cf2fad4 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum.h +++ b/src/google/protobuf/compiler/csharp/csharp_enum.h @@ -41,14 +41,12 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class EnumGenerator : public SourceGeneratorBase { public: EnumGenerator(const EnumDescriptor* descriptor); ~EnumGenerator(); - void Generate(Writer* writer); + void Generate(io::Printer* printer); private: const EnumDescriptor* descriptor_; diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc index 28f5a05c..51a95b9f 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc @@ -39,7 +39,6 @@ #include <google/protobuf/compiler/csharp/csharp_helpers.h> #include <google/protobuf/compiler/csharp/csharp_enum_field.h> -#include <google/protobuf/compiler/csharp/csharp_writer.h> namespace google { namespace protobuf { @@ -54,39 +53,38 @@ EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor, EnumFieldGenerator::~EnumFieldGenerator() { } -void EnumFieldGenerator::GenerateParsingCode(Writer* writer) { - writer->WriteLine("object unknown;"); - writer->WriteLine("if(input.ReadEnum(ref result.$0$_, out unknown)) {", name()); +void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print(variables_, + "object unknown;\n" + "if(input.ReadEnum(ref result.$name$_, out unknown)) {\n"); if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine(" result.has$0$ = true;", property_name()); + printer->Print(variables_, + " result.has$property_name$ = true;\n"); } - writer->WriteLine("} else if(unknown is int) {"); + printer->Print("} else if(unknown is int) {\n"); if (!use_lite_runtime()) { - writer->WriteLine(" if (unknownFields == null) {"); // First unknown field - create builder now - writer->WriteLine( - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);"); - writer->WriteLine(" }"); - writer->WriteLine( - " unknownFields.MergeVarintField($0$, (ulong)(int)unknown);", - number()); + printer->Print(variables_, + " if (unknownFields == null) {\n" // First unknown field - create builder now + " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" + " }\n" + " unknownFields.MergeVarintField($number$, (ulong)(int)unknown);\n"); } - writer->WriteLine("}"); + printer->Print("}\n"); } -void EnumFieldGenerator::GenerateSerializationCode(Writer* writer) { - writer->WriteLine("if ($0$) {", has_property_check); - writer->WriteLine( - " output.WriteEnum($0$, field_names[$2$], (int) $1$, $1$);", number(), - property_name(), field_ordinal()); - writer->WriteLine("}"); +void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + printer->Print(variables_, + "if ($has_property_check$) {\n" + " output.WriteEnum($number$, field_names[$field_ordinal$], (int) $property_name$, $property_name$);\n" + "}\n"); } -void EnumFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { - writer->WriteLine("if ($0$) {", has_property_check); - writer->WriteLine( - " size += pb::CodedOutputStream.ComputeEnumSize($0$, (int) $1$);", - number(), property_name()); - writer->WriteLine("}"); +void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n" + "}\n"); } EnumOneofFieldGenerator::EnumOneofFieldGenerator(const FieldDescriptor* descriptor, @@ -97,41 +95,40 @@ EnumOneofFieldGenerator::EnumOneofFieldGenerator(const FieldDescriptor* descript EnumOneofFieldGenerator::~EnumOneofFieldGenerator() { } -void EnumOneofFieldGenerator::GenerateParsingCode(Writer* writer) { - writer->WriteLine("object unknown;"); - writer->WriteLine("$0$ enumValue = $1$;", type_name(), default_value()); - writer->WriteLine("if(input.ReadEnum(ref enumValue, out unknown)) {", - name()); - writer->WriteLine(" result.$0$_ = enumValue;", oneof_name()); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", - oneof_name(), oneof_property_name(), property_name()); - writer->WriteLine("} else if(unknown is int) {"); +void EnumOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "object unknown;\n" + "$type_name$ enumValue = $default_value$;\n" + "if(input.ReadEnum(ref enumValue, out unknown)) {\n" + " result.$oneof_name$_ = enumValue;\n" + " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + "} else if(unknown is int) {\n"); if (!use_lite_runtime()) { - writer->WriteLine(" if (unknownFields == null) {"); // First unknown field - create builder now - writer->WriteLine( - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);"); - writer->WriteLine(" }"); - writer->WriteLine( - " unknownFields.MergeVarintField($0$, (ulong)(int)unknown);", - number()); + printer->Print( + variables_, + " if (unknownFields == null) {\n" // First unknown field - create builder now + " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" + " }\n" + " unknownFields.MergeVarintField($number$, (ulong)(int)unknown);\n"); } - writer->WriteLine("}"); + printer->Print("}\n"); } -void EnumOneofFieldGenerator::GenerateSerializationCode(Writer* writer) { - writer->WriteLine("if ($0$) {", has_property_check); - writer->WriteLine( - " output.WriteEnum($0$, field_names[$2$], (int) $1$, $1$);", number(), - property_name(), field_ordinal()); - writer->WriteLine("}"); +void EnumOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " output.WriteEnum($number$, field_names[$field_ordinal$], (int) $property_name$, $property_name$);\n" + "}\n"); } -void EnumOneofFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { - writer->WriteLine("if ($0$) {", has_property_check); - writer->WriteLine( - " size += pb::CodedOutputStream.ComputeEnumSize($0$, (int) $1$);", - number(), property_name()); - writer->WriteLine("}"); +void EnumOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n" + "}\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_enum_field.h index c6b7b848..e627b7cc 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.h @@ -41,16 +41,14 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class EnumFieldGenerator : public PrimitiveFieldGenerator { public: EnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~EnumFieldGenerator(); - virtual void GenerateParsingCode(Writer* writer); - virtual void GenerateSerializationCode(Writer* writer); - virtual void GenerateSerializedSizeCode(Writer* writer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); @@ -61,9 +59,9 @@ class EnumOneofFieldGenerator : public PrimitiveOneofFieldGenerator { EnumOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~EnumOneofFieldGenerator(); - virtual void GenerateParsingCode(Writer* writer); - virtual void GenerateSerializationCode(Writer* writer); - virtual void GenerateSerializedSizeCode(Writer* writer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator); diff --git a/src/google/protobuf/compiler/csharp/csharp_extension.cc b/src/google/protobuf/compiler/csharp/csharp_extension.cc index 2bac320d..8b665ae4 100644 --- a/src/google/protobuf/compiler/csharp/csharp_extension.cc +++ b/src/google/protobuf/compiler/csharp/csharp_extension.cc @@ -39,7 +39,6 @@ #include <google/protobuf/compiler/csharp/csharp_extension.h> #include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_writer.h> #include <google/protobuf/compiler/csharp/csharp_field_base.h> using google::protobuf::internal::scoped_ptr; @@ -52,20 +51,34 @@ namespace csharp { ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor) : FieldGeneratorBase(descriptor, 0) { if (descriptor_->extension_scope()) { - scope_ = GetClassName(descriptor_->extension_scope()); + variables_["scope"] = GetClassName(descriptor_->extension_scope()); } else { - scope_ = GetFullUmbrellaClassName(descriptor_->file()); + variables_["scope"] = GetFullUmbrellaClassName(descriptor_->file()); + } + variables_["extends"] = GetClassName(descriptor_->containing_type()); + variables_["capitalized_type_name"] = capitalized_type_name(); + variables_["full_name"] = descriptor_->full_name(); + variables_["access_level"] = class_access_level(); + variables_["index"] = SimpleItoa(descriptor_->index()); + variables_["property_name"] = property_name(); + variables_["type_name"] = type_name(); + if (use_lite_runtime()) { + variables_["generated_extension"] = descriptor_->is_repeated() ? + "GeneratedRepeatExtensionLite" : "GeneratedExtensionLite"; + } else { + variables_["generated_extension"] = descriptor_->is_repeated() ? + "GeneratedRepeatExtension" : "GeneratedExtension"; } - extends_ = GetClassName(descriptor_->containing_type()); } ExtensionGenerator::~ExtensionGenerator() { } -void ExtensionGenerator::Generate(Writer* writer) { - writer->WriteLine("public const int $0$ = $1$;", - GetFieldConstantName(descriptor_), - SimpleItoa(descriptor_->number())); +void ExtensionGenerator::Generate(io::Printer* printer) { + printer->Print( + "public const int $constant_name$ = $number$;\n", + "constant_name", GetFieldConstantName(descriptor_), + "number", SimpleItoa(descriptor_->number())); if (use_lite_runtime()) { // TODO(jtattermusch): include the following check @@ -75,36 +88,34 @@ void ExtensionGenerator::Generate(Writer* writer) { // "option message_set_wire_format = true; is not supported in Lite runtime extensions."); //} - writer->Write("$0$ ", class_access_level()); - writer->WriteLine( - "static pb::$3$<$0$, $1$> $2$;", - extends_, - type_name(), - property_name(), - descriptor_->is_repeated() ? - "GeneratedRepeatExtensionLite" : "GeneratedExtensionLite"); + printer->Print( + variables_, + "$access_level$ static pb::$generated_extension$<$extends$, $type_name$> $property_name$;\n"); } else if (descriptor_->is_repeated()) { - writer->WriteLine( - "$0$ static pb::GeneratedExtensionBase<scg::IList<$1$>> $2$;", - class_access_level(), type_name(), property_name()); + printer->Print( + variables_, + "$access_level$ static pb::GeneratedExtensionBase<scg::IList<$type_name$>> $property_name$;\n"); } else { - writer->WriteLine("$0$ static pb::GeneratedExtensionBase<$1$> $2$;", - class_access_level(), type_name(), property_name()); + printer->Print( + variables_, + "$access_level$ static pb::GeneratedExtensionBase<$type_name$> $property_name$;\n"); } } -void ExtensionGenerator::GenerateStaticVariableInitializers(Writer* writer) { +void ExtensionGenerator::GenerateStaticVariableInitializers(io::Printer* printer) { if (use_lite_runtime()) { - writer->WriteLine("$0$.$1$ = ", scope_, property_name()); - writer->Indent(); - writer->WriteLine( - "new pb::$0$<$1$, $2$>(", - descriptor_->is_repeated() ? - "GeneratedRepeatExtensionLite" : "GeneratedExtensionLite", - extends_, type_name()); - writer->Indent(); - writer->WriteLine("\"$0$\",", descriptor_->full_name()); - writer->WriteLine("$0$.DefaultInstance,", extends_); + printer->Print( + variables_, + "$scope$.$property_name$ = \n"); + printer->Indent(); + printer->Print( + variables_, + "new pb::$generated_extension$<$extends$, $type_name$>(\n"); + printer->Indent(); + printer->Print( + variables_, + "\"$full_name$\",\n" + "$extends$.DefaultInstance,\n"); if (!descriptor_->is_repeated()) { std::string default_val; if (descriptor_->has_default_value()) { @@ -112,52 +123,59 @@ void ExtensionGenerator::GenerateStaticVariableInitializers(Writer* writer) { } else { default_val = is_nullable_type() ? "null" : ("default(" + type_name() + ")"); } - writer->WriteLine("$0$,", default_val); + printer->Print("$default_val$,\n", "default_val", default_val); } - writer->WriteLine( - "$0$,", - (GetCSharpType(descriptor_->type()) == CSHARPTYPE_MESSAGE) ? - type_name() + ".DefaultInstance" : "null"); - writer->WriteLine( - "$0$,", - (GetCSharpType(descriptor_->type()) == CSHARPTYPE_ENUM) ? - "new EnumLiteMap<" + type_name() + ">()" : "null"); - writer->WriteLine("$0$.$1$FieldNumber,", scope_, - GetPropertyName(descriptor_)); - writer->Write("pbd::FieldType.$0$", capitalized_type_name()); + printer->Print( + "$message_val$,\n", + "message_val", + (GetCSharpType(descriptor_->type()) == CSHARPTYPE_MESSAGE) ? + type_name() + ".DefaultInstance" : "null"); + printer->Print( + "$enum_val$,\n", + "enum_val", + (GetCSharpType(descriptor_->type()) == CSHARPTYPE_ENUM) ? + "new EnumLiteMap<" + type_name() + ">()" : "null"); + printer->Print( + variables_, + "$scope$.$property_name$FieldNumber,\n" + "pbd::FieldType.$capitalized_type_name$"); if (descriptor_->is_repeated()) { - writer->WriteLine(","); - writer->Write(descriptor_->is_packed() ? "true" : "false"); + printer->Print( + ",\n" + "$is_packed$", + "is_packed", descriptor_->is_packed() ? "true" : "false"); } - writer->Outdent(); - writer->WriteLine(");"); - writer->Outdent(); + printer->Outdent(); + printer->Print(");\n"); + printer->Outdent(); } else if (descriptor_->is_repeated()) { - writer->WriteLine( - "$0$.$1$ = pb::GeneratedRepeatExtension<$2$>.CreateInstance($0$.Descriptor.Extensions[$3$]);", - scope_, property_name(), type_name(), SimpleItoa(descriptor_->index())); + printer->Print( + variables_, + "$scope$.$property_name$ = pb::GeneratedRepeatExtension<$type_name$>.CreateInstance($scope$.Descriptor.Extensions[$index$]);\n"); } else { - writer->WriteLine( - "$0$.$1$ = pb::GeneratedSingleExtension<$2$>.CreateInstance($0$.Descriptor.Extensions[$3$]);", - scope_, property_name(), type_name(), SimpleItoa(descriptor_->index())); + printer->Print( + variables_, + "$scope$.$property_name$ = pb::GeneratedSingleExtension<$type_name$>.CreateInstance($scope$.Descriptor.Extensions[$index$]);\n"); } } -void ExtensionGenerator::GenerateExtensionRegistrationCode(Writer* writer) { - writer->WriteLine("registry.Add($0$.$1$);", scope_, property_name()); +void ExtensionGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) { + printer->Print( + variables_, + "registry.Add($scope$.$property_name$);\n"); } -void ExtensionGenerator::WriteHash(Writer* writer) { +void ExtensionGenerator::WriteHash(io::Printer* printer) { } -void ExtensionGenerator::WriteEquals(Writer* writer) { +void ExtensionGenerator::WriteEquals(io::Printer* printer) { } -void ExtensionGenerator::WriteToString(Writer* writer) { +void ExtensionGenerator::WriteToString(io::Printer* printer) { } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_extension.h b/src/google/protobuf/compiler/csharp/csharp_extension.h index 203f6e5e..f251a21c 100644 --- a/src/google/protobuf/compiler/csharp/csharp_extension.h +++ b/src/google/protobuf/compiler/csharp/csharp_extension.h @@ -41,28 +41,26 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class ExtensionGenerator : public FieldGeneratorBase { public: ExtensionGenerator(const FieldDescriptor* descriptor); ~ExtensionGenerator(); - void GenerateStaticVariableInitializers(Writer* writer); - void GenerateExtensionRegistrationCode(Writer* writer); - void Generate(Writer* writer); + void GenerateStaticVariableInitializers(io::Printer* printer); + void GenerateExtensionRegistrationCode(io::Printer* printer); + void Generate(io::Printer* printer); - virtual void WriteHash(Writer* writer); - virtual void WriteEquals(Writer* writer); - virtual void WriteToString(Writer* writer); + virtual void WriteHash(io::Printer* printer); + virtual void WriteEquals(io::Printer* printer); + virtual void WriteToString(io::Printer* printer); - virtual void GenerateMembers(Writer* writer) {}; - virtual void GenerateBuilderMembers(Writer* writer) {}; - virtual void GenerateMergingCode(Writer* writer) {}; - virtual void GenerateBuildingCode(Writer* writer) {}; - virtual void GenerateParsingCode(Writer* writer) {}; - virtual void GenerateSerializationCode(Writer* writer) {}; - virtual void GenerateSerializedSizeCode(Writer* writer) {}; + virtual void GenerateMembers(io::Printer* printer) {}; + virtual void GenerateBuilderMembers(io::Printer* printer) {}; + virtual void GenerateMergingCode(io::Printer* printer) {}; + virtual void GenerateBuildingCode(io::Printer* printer) {}; + virtual void GenerateParsingCode(io::Printer* printer) {}; + virtual void GenerateSerializationCode(io::Printer* printer) {}; + virtual void GenerateSerializedSizeCode(io::Printer* printer) {}; private: std::string scope_; diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index dfc803e6..c3ce426b 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -41,7 +41,6 @@ #include <google/protobuf/compiler/csharp/csharp_field_base.h> #include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_writer.h> using google::protobuf::internal::scoped_ptr; @@ -50,35 +49,72 @@ namespace protobuf { namespace compiler { namespace csharp { +void FieldGeneratorBase::SetCommonFieldVariables( + map<string, string>* variables) { + (*variables)["property_name"] = property_name(); + (*variables)["type_name"] = type_name(); + (*variables)["name"] = name(); + (*variables)["descriptor_name"] = descriptor_->name(); + (*variables)["default_value"] = default_value(); + if (has_default_value()) { + (*variables)["name_def_message"] = + (*variables)["name"] + "_ = " + (*variables)["default_value"]; + } else { + (*variables)["name_def_message"] = (*variables)["name"] + "_"; + } + (*variables)["capitalized_type_name"] = capitalized_type_name(); + (*variables)["number"] = number(); + (*variables)["field_ordinal"] = field_ordinal(); + if (SupportFieldPresence(descriptor_->file())) { + (*variables)["has_property_check"] = "has" + (*variables)["property_name"]; + (*variables)["other_has_property_check"] = "other.Has" + (*variables)["property_name"]; + } else { + (*variables)["has_property_check"] = + (*variables)["property_name"] + " != " + (*variables)["default_value"]; + (*variables)["other_has_property_check"] = "other." + + (*variables)["property_name"] + " != " + (*variables)["default_value"]; + } +} + +void FieldGeneratorBase::SetCommonOneofFieldVariables( + map<string, string>* variables) { + (*variables)["oneof_name"] = oneof_name(); + (*variables)["has_property_check"] = oneof_name() + "Case_ == " + oneof_property_name() + + "OneofCase." + property_name(); + (*variables)["oneof_property_name"] = oneof_property_name(); +} + FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor, int fieldOrdinal) : SourceGeneratorBase(descriptor->file()), descriptor_(descriptor), fieldOrdinal_(fieldOrdinal) { + SetCommonFieldVariables(&variables_); } FieldGeneratorBase::~FieldGeneratorBase() { } -void FieldGeneratorBase::AddDeprecatedFlag(Writer* writer) { +void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) { if (descriptor_->options().deprecated()) { - writer->WriteLine("[global::System.ObsoleteAttribute()]"); + printer->Print("[global::System.ObsoleteAttribute()]\n"); } } -void FieldGeneratorBase::AddNullCheck(Writer* writer) { - AddNullCheck(writer, "value"); +void FieldGeneratorBase::AddNullCheck(io::Printer* printer) { + AddNullCheck(printer, "value"); } -void FieldGeneratorBase::AddNullCheck(Writer* writer, const std::string& name) { +void FieldGeneratorBase::AddNullCheck(io::Printer* printer, const std::string& name) { if (is_nullable_type()) { - writer->WriteLine(" pb::ThrowHelper.ThrowIfNull($0$, \"$0$\");", name); + printer->Print(" pb::ThrowHelper.ThrowIfNull($name$, \"$name$\");\n", + "name", name); } } -void FieldGeneratorBase::AddPublicMemberAttributes(Writer* writer) { - AddDeprecatedFlag(writer); +void FieldGeneratorBase::AddPublicMemberAttributes(io::Printer* printer) { + AddDeprecatedFlag(printer); } std::string FieldGeneratorBase::oneof_property_name() { diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h index 312da12b..b1570587 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h @@ -49,27 +49,29 @@ class FieldGeneratorBase : public SourceGeneratorBase { FieldGeneratorBase(const FieldDescriptor* descriptor, int fieldOrdinal); ~FieldGeneratorBase(); - virtual void GenerateMembers(Writer* writer) = 0; - virtual void GenerateBuilderMembers(Writer* writer) = 0; - virtual void GenerateMergingCode(Writer* writer) = 0; - virtual void GenerateBuildingCode(Writer* writer) = 0; - virtual void GenerateParsingCode(Writer* writer) = 0; - virtual void GenerateSerializationCode(Writer* writer) = 0; - virtual void GenerateSerializedSizeCode(Writer* writer) = 0; - - virtual void WriteHash(Writer* writer) = 0; - virtual void WriteEquals(Writer* writer) = 0; - virtual void WriteToString(Writer* writer) = 0; + virtual void GenerateMembers(io::Printer* printer) = 0; + virtual void GenerateBuilderMembers(io::Printer* printer) = 0; + virtual void GenerateMergingCode(io::Printer* printer) = 0; + virtual void GenerateBuildingCode(io::Printer* printer) = 0; + virtual void GenerateParsingCode(io::Printer* printer) = 0; + virtual void GenerateSerializationCode(io::Printer* printer) = 0; + virtual void GenerateSerializedSizeCode(io::Printer* printer) = 0; + + virtual void WriteHash(io::Printer* printer) = 0; + virtual void WriteEquals(io::Printer* printer) = 0; + virtual void WriteToString(io::Printer* printer) = 0; protected: const FieldDescriptor* descriptor_; const int fieldOrdinal_; + map<string, string> variables_; - void AddDeprecatedFlag(Writer* writer); - void AddNullCheck(Writer* writer); - void AddNullCheck(Writer* writer, const std::string& name); + void AddDeprecatedFlag(io::Printer* printer); + void AddNullCheck(io::Printer* printer); + void AddNullCheck(io::Printer* printer, const std::string& name); - void AddPublicMemberAttributes(Writer* writer); + void AddPublicMemberAttributes(io::Printer* printer); + void SetCommonOneofFieldVariables(map<string, string>* variables); std::string oneof_property_name(); std::string oneof_name(); @@ -85,6 +87,7 @@ class FieldGeneratorBase : public SourceGeneratorBase { std::string field_ordinal(); private: + void SetCommonFieldVariables(map<string, string>* variables); std::string GetStringDefaultValueInternal(); std::string GetBytesDefaultValueInternal(); diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc index 64c4bd7d..2a416fac 100644 --- a/src/google/protobuf/compiler/csharp/csharp_generator.cc +++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc @@ -40,7 +40,6 @@ #include <google/protobuf/compiler/csharp/csharp_generator.h> #include <google/protobuf/compiler/csharp/csharp_umbrella_class.h> #include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_writer.h> using google::protobuf::internal::scoped_ptr; @@ -55,9 +54,9 @@ std::string GetOutputFile(const google::protobuf::FileDescriptor* file, const st } void GenerateFile(const google::protobuf::FileDescriptor* file, - Writer* writer) { + io::Printer* printer) { UmbrellaClassGenerator umbrellaGenerator(file); - umbrellaGenerator.Generate(writer); + umbrellaGenerator.Generate(printer); } bool Generator::Generate( @@ -83,9 +82,8 @@ bool Generator::Generate( scoped_ptr<io::ZeroCopyOutputStream> output( generator_context->Open(filename)); io::Printer printer(output.get(), '$'); - Writer writer(&printer); - GenerateFile(file, &writer); + GenerateFile(file, &printer); return true; } diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 22681235..66b87110 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -30,6 +30,7 @@ #include <sstream> #include <algorithm> +#include <map> #include <google/protobuf/compiler/code_generator.h> #include <google/protobuf/compiler/plugin.h> @@ -46,7 +47,6 @@ #include <google/protobuf/compiler/csharp/csharp_message.h> #include <google/protobuf/compiler/csharp/csharp_helpers.h> #include <google/protobuf/compiler/csharp/csharp_field_base.h> -#include <google/protobuf/compiler/csharp/csharp_writer.h> using google::protobuf::internal::scoped_ptr; @@ -105,7 +105,7 @@ std::string GetUniqueFileScopeIdentifier(const Descriptor* descriptor) { return "static_" + result; } -void MessageGenerator::GenerateStaticVariables(Writer* writer) { +void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { // Because descriptor.proto (Google.ProtocolBuffers.DescriptorProtos) is // used in the construction of descriptors, we have a tricky bootstrapping // problem. To help control static initialization order, we make sure all @@ -117,175 +117,184 @@ void MessageGenerator::GenerateStaticVariables(Writer* writer) { if (!use_lite_runtime()) { // The descriptor for this type. - std::string access = "internal"; - writer->WriteLine( - "$0$ static pbd::MessageDescriptor internal__$1$__Descriptor;", access, - identifier); - writer->WriteLine( - "$0$ static pb::FieldAccess.FieldAccessorTable<$1$, $1$.Builder> internal__$2$__FieldAccessorTable;", - access, full_class_name(), identifier); + printer->Print( + "internal static pbd::MessageDescriptor internal__$identifier$__Descriptor;\n" + "internal static pb::FieldAccess.FieldAccessorTable<$full_class_name$, $full_class_name$.Builder> internal__$identifier$__FieldAccessorTable;\n", + "identifier", GetUniqueFileScopeIdentifier(descriptor_), + "full_class_name", full_class_name()); } for (int i = 0; i < descriptor_->nested_type_count(); i++) { MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.GenerateStaticVariables(writer); + messageGenerator.GenerateStaticVariables(printer); } } -void MessageGenerator::GenerateStaticVariableInitializers(Writer* writer) { - std::string identifier = GetUniqueFileScopeIdentifier(descriptor_); - +void MessageGenerator::GenerateStaticVariableInitializers(io::Printer* printer) { + map<string, string> vars; + vars["identifier"] = GetUniqueFileScopeIdentifier(descriptor_); + vars["index"] = SimpleItoa(descriptor_->index()); + vars["full_class_name"] = full_class_name(); + if (descriptor_->containing_type() != NULL) { + vars["parent"] = GetUniqueFileScopeIdentifier( + descriptor_->containing_type()); + } if (!use_lite_runtime()) { - writer->Write("internal__$0$__Descriptor = ", identifier); + printer->Print(vars, "internal__$identifier$__Descriptor = "); if (!descriptor_->containing_type()) { - writer->WriteLine("Descriptor.MessageTypes[$0$];", - SimpleItoa(descriptor_->index())); + printer->Print(vars, "Descriptor.MessageTypes[$index$];\n"); } else { - writer->WriteLine( - "internal__$0$__Descriptor.NestedTypes[$1$];", - GetUniqueFileScopeIdentifier(descriptor_->containing_type()), - SimpleItoa(descriptor_->index())); + printer->Print(vars, "internal__$parent$__Descriptor.NestedTypes[$index$];\n"); } - writer->WriteLine("internal__$0$__FieldAccessorTable = ", identifier); - writer->WriteLine( - " new pb::FieldAccess.FieldAccessorTable<$1$, $1$.Builder>(internal__$0$__Descriptor,", - identifier, full_class_name()); - writer->Write(" new string[] { "); + printer->Print( + vars, + "internal__$identifier$__FieldAccessorTable = \n" + " new pb::FieldAccess.FieldAccessorTable<$full_class_name$, $full_class_name$.Builder>(internal__$identifier$__Descriptor,\n"); + printer->Print(" new string[] { "); for (int i = 0; i < descriptor_->field_count(); i++) { - writer->Write("\"$0$\", ", GetPropertyName(descriptor_->field(i))); + printer->Print("\"$property_name$\", ", + "property_name", GetPropertyName(descriptor_->field(i))); } for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - writer->Write("\"$0$\", ", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); + printer->Print("\"$oneof_name$\", ", + "oneof_name", + UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); } - writer->WriteLine("});"); + printer->Print("});\n"); } // Generate static member initializers for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.GenerateStaticVariableInitializers(writer); + messageGenerator.GenerateStaticVariableInitializers(printer); } for (int i = 0; i < descriptor_->extension_count(); i++) { ExtensionGenerator extensionGenerator(descriptor_->extension(i)); - extensionGenerator.GenerateStaticVariableInitializers(writer); + extensionGenerator.GenerateStaticVariableInitializers(printer); } } -void MessageGenerator::Generate(Writer* writer) { - writer->WriteLine( - "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); - WriteGeneratedCodeAttributes(writer); - writer->WriteLine( - "$0$ sealed partial class $1$ : pb::$2$Message$3$<$1$, $1$.Builder> {", - class_access_level(), class_name(), - descriptor_->extension_range_count() > 0 ? "Extendable" : "Generated", - runtime_suffix()); - writer->Indent(); - writer->WriteLine("private $0$() { }", class_name()); // Private ctor. - // Must call MakeReadOnly() to make sure all lists are made read-only - writer->WriteLine( - "private static readonly $0$ defaultInstance = new $0$().MakeReadOnly();", - class_name()); +void MessageGenerator::Generate(io::Printer* printer) { + map<string, string> vars; + vars["class_name"] = class_name(); + vars["access_level"] = class_access_level(); + vars["extendable_or_generated"] = descriptor_->extension_range_count() > 0 ? + "Extendable" : "Generated"; + vars["suffix"] = runtime_suffix(); + vars["umbrella_class_name"] = GetFullUmbrellaClassName(descriptor_->file()); + vars["identifier"] = GetUniqueFileScopeIdentifier(descriptor_); + + printer->Print( + "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); + WriteGeneratedCodeAttributes(printer); + printer->Print( + vars, + "$access_level$ sealed partial class $class_name$ : pb::$extendable_or_generated$Message$suffix$<$class_name$, $class_name$.Builder> {\n"); + printer->Indent(); + printer->Print( + vars, + "private $class_name$() { }\n" // Private ctor. + // Must call MakeReadOnly() to make sure all lists are made read-only + "private static readonly $class_name$ defaultInstance = new $class_name$().MakeReadOnly();\n"); if (optimize_speed()) { - writer->WriteLine( - "private static readonly string[] _$0$FieldNames = new string[] { $2$$1$$2$ };", - UnderscoresToCamelCase(class_name(), false), - JoinStrings(field_names(), "\", \""), - field_names().size() > 0 ? "\"" : ""); + printer->Print( + "private static readonly string[] _$name$FieldNames = " + "new string[] { $slash$$field_names$$slash$ };\n", + "name", UnderscoresToCamelCase(class_name(), false), + "field_names", JoinStrings(field_names(), "\", \""), + "slash", field_names().size() > 0 ? "\"" : ""); std::vector<std::string> tags; for (int i = 0; i < field_names().size(); i++) { uint32 tag = internal::WireFormat::MakeTag( descriptor_->FindFieldByName(field_names()[i])); tags.push_back(SimpleItoa(tag)); } - writer->WriteLine( - "private static readonly uint[] _$0$FieldTags = new uint[] { $1$ };", - UnderscoresToCamelCase(class_name(), false), JoinStrings(tags, ", ")); - } - writer->WriteLine("public static $0$ DefaultInstance {", class_name()); - writer->WriteLine(" get { return defaultInstance; }"); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine("public override $0$ DefaultInstanceForType {", - class_name()); - writer->WriteLine(" get { return DefaultInstance; }"); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine("protected override $0$ ThisMessage {", class_name()); - writer->WriteLine(" get { return this; }"); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Print( + "private static readonly uint[] _$name$FieldTags = new uint[] { $tags$ };\n", + "name", UnderscoresToCamelCase(class_name(), false), + "tags", JoinStrings(tags, ", ")); + } + printer->Print( + vars, + "public static $class_name$ DefaultInstance {\n" + " get { return defaultInstance; }\n" + "}\n" + "\n" + "public override $class_name$ DefaultInstanceForType {\n" + " get { return DefaultInstance; }\n" + "}\n" + "\n" + "protected override $class_name$ ThisMessage {\n" + " get { return this; }\n" + "}\n\n"); + if (!use_lite_runtime()) { - writer->WriteLine("public static pbd::MessageDescriptor Descriptor {"); - writer->WriteLine(" get { return $0$.internal__$1$__Descriptor; }", - GetFullUmbrellaClassName(descriptor_->file()), - GetUniqueFileScopeIdentifier(descriptor_)); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine( - "protected override pb::FieldAccess.FieldAccessorTable<$0$, $0$.Builder> InternalFieldAccessors {", - class_name()); - writer->WriteLine(" get { return $0$.internal__$1$__FieldAccessorTable; }", - GetFullUmbrellaClassName(descriptor_->file()), - GetUniqueFileScopeIdentifier(descriptor_)); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Print( + vars, + "public static pbd::MessageDescriptor Descriptor {\n" + " get { return $umbrella_class_name$.internal__$identifier$__Descriptor; }\n" + "}\n" + "\n" + "protected override pb::FieldAccess.FieldAccessorTable<$class_name$, $class_name$.Builder> InternalFieldAccessors {\n" + " get { return $umbrella_class_name$.internal__$identifier$__FieldAccessorTable; }\n" + "}\n" + "\n"); } // Extensions don't need to go in an extra nested type for (int i = 0; i < descriptor_->extension_count(); i++) { ExtensionGenerator extensionGenerator(descriptor_->extension(i)); - extensionGenerator.Generate(writer); + extensionGenerator.Generate(printer); } if (descriptor_->enum_type_count() + descriptor_->nested_type_count() > 0) { - writer->WriteLine("#region Nested types"); - writer->WriteLine( - "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); - WriteGeneratedCodeAttributes(writer); - writer->WriteLine("public static partial class Types {"); - writer->Indent(); + printer->Print("#region Nested types\n" + "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); + WriteGeneratedCodeAttributes(printer); + printer->Print("public static partial class Types {\n"); + printer->Indent(); for (int i = 0; i < descriptor_->enum_type_count(); i++) { EnumGenerator enumGenerator(descriptor_->enum_type(i)); - enumGenerator.Generate(writer); + enumGenerator.Generate(printer); } for (int i = 0; i < descriptor_->nested_type_count(); i++) { MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.Generate(writer); + messageGenerator.Generate(printer); } - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine("#endregion"); - writer->WriteLine(); + printer->Outdent(); + printer->Print("}\n" + "#endregion\n" + "\n"); } // oneof for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - string name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); - string property_name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); - writer->WriteLine("private object $0$_;", name); - writer->WriteLine("public enum $0$OneofCase {", property_name); - writer->Indent(); + vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); + vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); + printer->Print( + vars, + "private object $name$_;\n" + "public enum $property_name$OneofCase {\n"); + printer->Indent(); for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - writer->WriteLine("$0$ = $1$,", - GetPropertyName(field), - SimpleItoa(field->number())); + printer->Print("$field_property_name$ = $index$,\n", + "field_property_name", GetPropertyName(field), + "index", SimpleItoa(field->number())); } - writer->WriteLine("None = 0,"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine("private $0$OneofCase $1$Case_ = $0$OneofCase.None;", - property_name, name); - writer->WriteLine("public $0$OneofCase $0$Case {", property_name); - writer->WriteLine(" get { return $0$Case_; }", name); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Print("None = 0,\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print( + vars, + "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n" + "public $property_name$OneofCase $property_name$Case {\n" + " get { return $name$Case_; }\n" + "}\n\n"); } // Fields @@ -293,108 +302,119 @@ void MessageGenerator::Generate(Writer* writer) { const FieldDescriptor* fieldDescriptor = descriptor_->field(i); // Rats: we lose the debug comment here :( - writer->WriteLine("public const int $0$ = $1$;", - GetFieldConstantName(fieldDescriptor), - SimpleItoa(fieldDescriptor->number())); + printer->Print( + "public const int $field_constant_name$ = $index$;\n", + "field_constant_name", GetFieldConstantName(fieldDescriptor), + "index", SimpleItoa(fieldDescriptor->number())); scoped_ptr<FieldGeneratorBase> generator( CreateFieldGeneratorInternal(fieldDescriptor)); - generator->GenerateMembers(writer); - writer->WriteLine(); + generator->GenerateMembers(printer); + printer->Print("\n"); } if (optimize_speed()) { if (SupportFieldPresence(descriptor_->file())) { - GenerateIsInitialized(writer); + GenerateIsInitialized(printer); } - GenerateMessageSerializationMethods(writer); + GenerateMessageSerializationMethods(printer); } if (use_lite_runtime()) { - GenerateLiteRuntimeMethods(writer); + GenerateLiteRuntimeMethods(printer); } - GenerateParseFromMethods(writer); - GenerateBuilder(writer); + GenerateParseFromMethods(printer); + GenerateBuilder(printer); // Force the static initialization code for the file to run, since it may // initialize static variables declared in this class. - writer->WriteLine("static $0$() {", class_name()); + printer->Print(vars, "static $class_name$() {\n"); // We call object.ReferenceEquals() just to make it a valid statement on its own. // Another option would be GetType(), but that causes problems in DescriptorProtoFile, // where the bootstrapping is somewhat recursive - type initializers call // each other, effectively. We temporarily see Descriptor as null. - writer->WriteLine(" object.ReferenceEquals($0$.Descriptor, null);", - GetFullUmbrellaClassName(descriptor_->file())); - writer->WriteLine("}"); + printer->Print( + vars, + " object.ReferenceEquals($umbrella_class_name$.Descriptor, null);\n" + "}\n"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("\n"); } -void MessageGenerator::GenerateLiteRuntimeMethods(Writer* writer) { +void MessageGenerator::GenerateLiteRuntimeMethods(io::Printer* printer) { + map<string, string> vars; + vars["class_name"] = class_name(); + bool callbase = descriptor_->extension_range_count() > 0; - writer->WriteLine("#region Lite runtime methods"); - writer->WriteLine("public override int GetHashCode() {"); - writer->Indent(); - writer->WriteLine("int hash = GetType().GetHashCode();"); + printer->Print("#region Lite runtime methods\n" + "public override int GetHashCode() {\n"); + printer->Indent(); + printer->Print("int hash = GetType().GetHashCode();\n"); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); if (field->containing_oneof() == NULL) { scoped_ptr<FieldGeneratorBase> generator( CreateFieldGeneratorInternal(field)); - generator->WriteHash(writer); + generator->WriteHash(printer); } } for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { string name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); string property_name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); - writer->WriteLine("if ($0$Case_ != $1$OneofCase.None) {", name, property_name); - writer->WriteLine(" hash ^= $0$_.GetHashCode();", name); - writer->WriteLine("}"); + printer->Print( + "if ($name$Case_ != $property_name$OneofCase.None) {\n" + " hash ^= $name$_.GetHashCode();\n" + "}\n", + "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false), + "property_name", + UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); } if (callbase) { - writer->WriteLine("hash ^= base.GetHashCode();"); - } - writer->WriteLine("return hash;"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); - - writer->WriteLine("public override bool Equals(object obj) {"); - writer->Indent(); - writer->WriteLine("$0$ other = obj as $0$;", class_name()); - writer->WriteLine("if (other == null) return false;"); + printer->Print("hash ^= base.GetHashCode();\n"); + } + printer->Print("return hash;\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("\n"); + + printer->Print("public override bool Equals(object obj) {\n"); + printer->Indent(); + printer->Print( + vars, + "$class_name$ other = obj as $class_name$;\n" + "if (other == null) return false;\n"); for (int i = 0; i < descriptor_->field_count(); i++) { scoped_ptr<FieldGeneratorBase> generator( CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->WriteEquals(writer); + generator->WriteEquals(printer); } if (callbase) { - writer->WriteLine("if (!base.Equals(other)) return false;"); + printer->Print("if (!base.Equals(other)) return false;\n"); } - writer->WriteLine("return true;"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Print("return true;\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("\n"); - writer->WriteLine( - "public override void PrintTo(global::System.IO.TextWriter writer) {"); - writer->Indent(); + printer->Print( + "public override void PrintTo(global::System.IO.TextWriter writer) {\n"); + printer->Indent(); for (int i = 0; i < fields_by_number().size(); i++) { scoped_ptr<FieldGeneratorBase> generator( CreateFieldGeneratorInternal(fields_by_number()[i])); - generator->WriteToString(writer); + generator->WriteToString(printer); } if (callbase) { - writer->WriteLine("base.PrintTo(writer);"); + printer->Print("base.PrintTo(writer);\n"); } - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine("#endregion"); - writer->WriteLine(); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("#endregion\n"); + printer->Print("\n"); } bool CompareExtensionRangesStart(const Descriptor::ExtensionRange* r1, @@ -402,7 +422,7 @@ bool CompareExtensionRangesStart(const Descriptor::ExtensionRange* r1, return r1->start < r2->start; } -void MessageGenerator::GenerateMessageSerializationMethods(Writer* writer) { +void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) { std::vector<const Descriptor::ExtensionRange*> extension_ranges_sorted; for (int i = 0; i < descriptor_->extension_range_count(); i++) { extension_ranges_sorted.push_back(descriptor_->extension_range(i)); @@ -410,439 +430,442 @@ void MessageGenerator::GenerateMessageSerializationMethods(Writer* writer) { std::sort(extension_ranges_sorted.begin(), extension_ranges_sorted.end(), CompareExtensionRangesStart); - writer->WriteLine( - "public override void WriteTo(pb::ICodedOutputStream output) {"); - writer->Indent(); + printer->Print( + "public override void WriteTo(pb::ICodedOutputStream output) {\n"); + printer->Indent(); // Make sure we've computed the serialized length, so that packed fields are generated correctly. - writer->WriteLine("CalcSerializedSize();"); - writer->WriteLine("string[] field_names = _$0$FieldNames;", - UnderscoresToCamelCase(class_name(), false)); + printer->Print("CalcSerializedSize();\n" + "string[] field_names = _$class_name$FieldNames;\n", + "class_name", UnderscoresToCamelCase(class_name(), false)); if (descriptor_->extension_range_count()) { - writer->WriteLine( - "pb::ExtendableMessage$1$<$0$, $0$.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this);", - class_name(), runtime_suffix()); + printer->Print( + "pb::ExtendableMessage$runtime_suffix$<$class_name$, $class_name$.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this);\n", + "class_name", class_name(), + "runtime_suffix", runtime_suffix()); } // Merge the fields and the extension ranges, both sorted by field number. for (int i = 0, j = 0; i < fields_by_number().size() || j < extension_ranges_sorted.size();) { if (i == fields_by_number().size()) { - GenerateSerializeOneExtensionRange(writer, extension_ranges_sorted[j++]); + GenerateSerializeOneExtensionRange(printer, extension_ranges_sorted[j++]); } else if (j == extension_ranges_sorted.size()) { - GenerateSerializeOneField(writer, fields_by_number()[i++]); + GenerateSerializeOneField(printer, fields_by_number()[i++]); } else if (fields_by_number()[i]->number() < extension_ranges_sorted[j]->start) { - GenerateSerializeOneField(writer, fields_by_number()[i++]); + GenerateSerializeOneField(printer, fields_by_number()[i++]); } else { - GenerateSerializeOneExtensionRange(writer, extension_ranges_sorted[j++]); + GenerateSerializeOneExtensionRange(printer, extension_ranges_sorted[j++]); } } if (!use_lite_runtime()) { if (descriptor_->options().message_set_wire_format()) { - writer->WriteLine("UnknownFields.WriteAsMessageSetTo(output);"); + printer->Print("UnknownFields.WriteAsMessageSetTo(output);\n"); } else { - writer->WriteLine("UnknownFields.WriteTo(output);"); + printer->Print("UnknownFields.WriteTo(output);\n"); } } - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine("private int memoizedSerializedSize = -1;"); - writer->WriteLine("public override int SerializedSize {"); - writer->Indent(); - writer->WriteLine("get {"); - writer->Indent(); - writer->WriteLine("int size = memoizedSerializedSize;"); - writer->WriteLine("if (size != -1) return size;"); - writer->WriteLine("return CalcSerializedSize();"); - writer->Outdent(); - writer->WriteLine("}"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); - - writer->WriteLine("private int CalcSerializedSize() {"); - writer->Indent(); - writer->WriteLine("int size = memoizedSerializedSize;"); - writer->WriteLine("if (size != -1) return size;"); - writer->WriteLine(); - writer->WriteLine("size = 0;"); + printer->Outdent(); + printer->Print( + "}\n" + "\n" + "private int memoizedSerializedSize = -1;\n" + "public override int SerializedSize {\n"); + printer->Indent(); + printer->Print("get {\n"); + printer->Indent(); + printer->Print( + "int size = memoizedSerializedSize;\n" + "if (size != -1) return size;\n" + "return CalcSerializedSize();\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("\n"); + + printer->Print("private int CalcSerializedSize() {\n"); + printer->Indent(); + printer->Print( + "int size = memoizedSerializedSize;\n" + "if (size != -1) return size;\n" + "\n" + "size = 0;\n"); for (int i = 0; i < descriptor_->field_count(); i++) { scoped_ptr<FieldGeneratorBase> generator( CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->GenerateSerializedSizeCode(writer); + generator->GenerateSerializedSizeCode(printer); } if (descriptor_->extension_range_count() > 0) { - writer->WriteLine("size += ExtensionsSerializedSize;"); + printer->Print("size += ExtensionsSerializedSize;\n"); } if (!use_lite_runtime()) { if (descriptor_->options().message_set_wire_format()) { - writer->WriteLine("size += UnknownFields.SerializedSizeAsMessageSet;"); + printer->Print("size += UnknownFields.SerializedSizeAsMessageSet;\n"); } else { - writer->WriteLine("size += UnknownFields.SerializedSize;"); + printer->Print("size += UnknownFields.SerializedSize;\n"); } } - writer->WriteLine("memoizedSerializedSize = size;"); - writer->WriteLine("return size;"); - writer->Outdent(); - writer->WriteLine("}"); + printer->Print( + "memoizedSerializedSize = size;\n" + "return size;\n"); + printer->Outdent(); + printer->Print("}\n"); } void MessageGenerator::GenerateSerializeOneField( - Writer* writer, const FieldDescriptor* fieldDescriptor) { + io::Printer* printer, const FieldDescriptor* fieldDescriptor) { scoped_ptr<FieldGeneratorBase> generator( CreateFieldGeneratorInternal(fieldDescriptor)); - generator->GenerateSerializationCode(writer); + generator->GenerateSerializationCode(printer); } void MessageGenerator::GenerateSerializeOneExtensionRange( - Writer* writer, const Descriptor::ExtensionRange* extensionRange) { - writer->WriteLine("extensionWriter.WriteUntil($0$, output);", - SimpleItoa(extensionRange->end)); + io::Printer* printer, const Descriptor::ExtensionRange* extensionRange) { + printer->Print("extensionWriter.WriteUntil($range_end$, output);\n", + "range_end", SimpleItoa(extensionRange->end)); } -void MessageGenerator::GenerateParseFromMethods(Writer* writer) { +void MessageGenerator::GenerateParseFromMethods(io::Printer* printer) { // Note: These are separate from GenerateMessageSerializationMethods() // because they need to be generated even for messages that are optimized // for code size. - - writer->WriteLine("public static $0$ ParseFrom(pb::ByteString data) {", - class_name()); - writer->WriteLine( - " return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();"); - writer->WriteLine("}"); - writer->WriteLine( - "public static $0$ ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {", - class_name()); - writer->WriteLine( - " return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();"); - writer->WriteLine("}"); - writer->WriteLine("public static $0$ ParseFrom(byte[] data) {", class_name()); - writer->WriteLine( - " return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();"); - writer->WriteLine("}"); - writer->WriteLine( - "public static $0$ ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {", - class_name()); - writer->WriteLine( - " return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();"); - writer->WriteLine("}"); - writer->WriteLine( - "public static $0$ ParseFrom(global::System.IO.Stream input) {", - class_name()); - writer->WriteLine( - " return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();"); - writer->WriteLine("}"); - writer->WriteLine( - "public static $0$ ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {", - class_name()); - writer->WriteLine( - " return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();"); - writer->WriteLine("}"); - writer->WriteLine( - "public static $0$ ParseDelimitedFrom(global::System.IO.Stream input) {", - class_name()); - writer->WriteLine( - " return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();"); - writer->WriteLine("}"); - writer->WriteLine( - "public static $0$ ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {", - class_name()); - writer->WriteLine( - " return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();"); - writer->WriteLine("}"); - writer->WriteLine( - "public static $0$ ParseFrom(pb::ICodedInputStream input) {", - class_name()); - writer->WriteLine( - " return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();"); - writer->WriteLine("}"); - writer->WriteLine( - "public static $0$ ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {", - class_name()); - writer->WriteLine( - " return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();"); - writer->WriteLine("}"); + map<string, string> vars; + vars["class_name"] = class_name(); + + printer->Print( + vars, + "public static $class_name$ ParseFrom(pb::ByteString data) {\n" + " return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();\n" + "}\n" + "public static $class_name$ ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {\n" + " return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();\n" + "}\n" + "public static $class_name$ ParseFrom(byte[] data) {\n" + " return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();\n" + "}\n" + "public static $class_name$ ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {\n" + " return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();\n" + "}\n" + "public static $class_name$ ParseFrom(global::System.IO.Stream input) {\n" + " return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();\n" + "}\n" + "public static $class_name$ ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {\n" + " return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();\n" + "}\n" + "public static $class_name$ ParseDelimitedFrom(global::System.IO.Stream input) {\n" + " return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();\n" + "}\n" + "public static $class_name$ ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {\n" + " return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();\n" + "}\n" + "public static $class_name$ ParseFrom(pb::ICodedInputStream input) {\n" + " return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();\n" + "}\n" + "public static $class_name$ ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {\n" + " return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();\n" + "}\n"); } -void MessageGenerator::GenerateBuilder(Writer* writer) { - writer->WriteLine("private $0$ MakeReadOnly() {", class_name()); - writer->Indent(); +void MessageGenerator::GenerateBuilder(io::Printer* printer) { + map<string, string> vars; + vars["class_name"] = class_name(); + vars["access_level"] = class_access_level(); + vars["extendable_or_generated"] = descriptor_->extension_range_count() > 0 ? + "Extendable" : "Generated"; + vars["suffix"] = runtime_suffix(); + + printer->Print(vars, "private $class_name$ MakeReadOnly() {\n"); + printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { scoped_ptr<FieldGeneratorBase> generator( CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->GenerateBuildingCode(writer); - } - writer->WriteLine("return this;"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); - - writer->WriteLine( - "public static Builder CreateBuilder() { return new Builder(); }"); - writer->WriteLine( - "public override Builder ToBuilder() { return CreateBuilder(this); }"); - writer->WriteLine( - "public override Builder CreateBuilderForType() { return new Builder(); }"); - writer->WriteLine("public static Builder CreateBuilder($0$ prototype) {", - class_name()); - writer->WriteLine(" return new Builder(prototype);"); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine( - "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); - WriteGeneratedCodeAttributes(writer); - writer->WriteLine( - "$0$ sealed partial class Builder : pb::$2$Builder$3$<$1$, Builder> {", - class_access_level(), class_name(), - descriptor_->extension_range_count() > 0 ? "Extendable" : "Generated", - runtime_suffix()); - writer->Indent(); - writer->WriteLine("protected override Builder ThisBuilder {"); - writer->WriteLine(" get { return this; }"); - writer->WriteLine("}"); - GenerateCommonBuilderMethods(writer); + generator->GenerateBuildingCode(printer); + } + printer->Print("return this;\n"); + printer->Outdent(); + printer->Print("}\n\n"); + + printer->Print( + vars, + "public static Builder CreateBuilder() { return new Builder(); }\n" + "public override Builder ToBuilder() { return CreateBuilder(this); }\n" + "public override Builder CreateBuilderForType() { return new Builder(); }\n" + "public static Builder CreateBuilder($class_name$ prototype) {\n" + " return new Builder(prototype);\n" + "}\n" + "\n" + "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); + WriteGeneratedCodeAttributes(printer); + printer->Print( + vars, + "$access_level$ sealed partial class Builder : pb::$extendable_or_generated$Builder$suffix$<$class_name$, Builder> {\n"); + printer->Indent(); + printer->Print( + "protected override Builder ThisBuilder {\n" + " get { return this; }\n" + "}\n"); + GenerateCommonBuilderMethods(printer); if (optimize_speed()) { - GenerateBuilderParsingMethods(writer); + GenerateBuilderParsingMethods(printer); } for (int i = 0; i < descriptor_->field_count(); i++) { scoped_ptr<FieldGeneratorBase> generator( CreateFieldGeneratorInternal(descriptor_->field(i))); - writer->WriteLine(); + printer->Print("\n"); // No field comment :( - generator->GenerateBuilderMembers(writer); + generator->GenerateBuilderMembers(printer); } // oneof for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - writer->WriteLine(); + printer->Print("\n"); string name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); string property_name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); - writer->WriteLine("public $0$OneofCase $0$Case {", property_name); - writer->WriteLine(" get { return result.$0$Case_; }", name); - writer->WriteLine("}"); - writer->WriteLine("public Builder Clear$0$() {", property_name); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_ = null;", name); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.None;", name, property_name); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - } - - writer->Outdent(); - writer->WriteLine("}"); + printer->Print( + "public $property_name$OneofCase $property_name$Case {\n" + " get { return result.$name$Case_; }\n" + "}\n" + "public Builder Clear$property_name$() {\n" + " PrepareBuilder();\n" + " result.$name$_ = null;\n" + " result.$name$Case_ = $property_name$OneofCase.None;\n" + " return this;\n" + "}\n", + "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false), + "property_name", + UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); + } + + printer->Outdent(); + printer->Print("}\n"); } -void MessageGenerator::GenerateCommonBuilderMethods(Writer* writer) { - //default constructor - writer->WriteLine("public Builder() {"); - //Durring static initialization of message, DefaultInstance is expected to return null. - writer->WriteLine(" result = DefaultInstance;"); - writer->WriteLine(" resultIsReadOnly = true;"); - writer->WriteLine("}"); - //clone constructor - writer->WriteLine("internal Builder($0$ cloneFrom) {", class_name()); - writer->WriteLine(" result = cloneFrom;"); - writer->WriteLine(" resultIsReadOnly = true;"); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine("private bool resultIsReadOnly;"); - writer->WriteLine("private $0$ result;", class_name()); - writer->WriteLine(); - writer->WriteLine("private $0$ PrepareBuilder() {", class_name()); - writer->WriteLine(" if (resultIsReadOnly) {"); - writer->WriteLine(" $0$ original = result;", class_name()); - writer->WriteLine(" result = new $0$();", class_name()); - writer->WriteLine(" resultIsReadOnly = false;"); - writer->WriteLine(" MergeFrom(original);"); - writer->WriteLine(" }"); - writer->WriteLine(" return result;"); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine("public override bool IsInitialized {"); - writer->WriteLine(" get { return result.IsInitialized; }"); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine("protected override $0$ MessageBeingBuilt {", class_name()); - writer->WriteLine(" get { return PrepareBuilder(); }"); - writer->WriteLine("}"); - writer->WriteLine(); +void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { + map<string, string> vars; + vars["class_name"] = class_name(); + vars["full_class_name"] = full_class_name(); + vars["suffix"] = runtime_suffix(); + + printer->Print( + vars, + //default constructor + "public Builder() {\n" + //Durring static initialization of message, DefaultInstance is expected to return null. + " result = DefaultInstance;\n" + " resultIsReadOnly = true;\n" + "}\n" + //clone constructor + "internal Builder($class_name$ cloneFrom) {\n" + " result = cloneFrom;\n" + " resultIsReadOnly = true;\n" + "}\n" + "\n" + "private bool resultIsReadOnly;\n" + "private $class_name$ result;\n" + "\n" + "private $class_name$ PrepareBuilder() {\n" + " if (resultIsReadOnly) {\n" + " $class_name$ original = result;\n" + " result = new $class_name$();\n" + " resultIsReadOnly = false;\n" + " MergeFrom(original);\n" + " }\n" + " return result;\n" + "}\n" + "\n" + "public override bool IsInitialized {\n" + " get { return result.IsInitialized; }\n" + "}\n" + "\n" + "protected override $class_name$ MessageBeingBuilt {\n" + " get { return PrepareBuilder(); }\n" + "}\n" + "\n"); //Not actually expecting that DefaultInstance would ever be null here; however, we will ensure it does not break - writer->WriteLine("public override Builder Clear() {"); - writer->WriteLine(" result = DefaultInstance;"); - writer->WriteLine(" resultIsReadOnly = true;"); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine("public override Builder Clone() {"); - writer->WriteLine(" if (resultIsReadOnly) {"); - writer->WriteLine(" return new Builder(result);"); - writer->WriteLine(" } else {"); - writer->WriteLine(" return new Builder().MergeFrom(result);"); - writer->WriteLine(" }"); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Print( + "public override Builder Clear() {\n" + " result = DefaultInstance;\n" + " resultIsReadOnly = true;\n" + " return this;\n" + "}\n" + "\n" + "public override Builder Clone() {\n" + " if (resultIsReadOnly) {\n" + " return new Builder(result);\n" + " } else {\n" + " return new Builder().MergeFrom(result);\n" + " }\n" + "}\n" + "\n"); if (!use_lite_runtime()) { - writer->WriteLine( - "public override pbd::MessageDescriptor DescriptorForType {"); - writer->WriteLine(" get { return $0$.Descriptor; }", full_class_name()); - writer->WriteLine("}"); - writer->WriteLine(); - } - writer->WriteLine("public override $0$ DefaultInstanceForType {", - class_name()); - writer->WriteLine(" get { return $0$.DefaultInstance; }", full_class_name()); - writer->WriteLine("}"); - writer->WriteLine(); - - writer->WriteLine("public override $0$ BuildPartial() {", class_name()); - writer->Indent(); - writer->WriteLine("if (resultIsReadOnly) {"); - writer->WriteLine(" return result;"); - writer->WriteLine("}"); - writer->WriteLine("resultIsReadOnly = true;"); - writer->WriteLine("return result.MakeReadOnly();"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Print( + vars, + "public override pbd::MessageDescriptor DescriptorForType {\n" + " get { return $full_class_name$.Descriptor; }\n" + "}\n\n"); + } + printer->Print( + vars, + "public override $class_name$ DefaultInstanceForType {\n" + " get { return $full_class_name$.DefaultInstance; }\n" + "}\n\n"); + + printer->Print( + vars, + "public override $class_name$ BuildPartial() {\n" + " if (resultIsReadOnly) {\n" + " return result;\n" + " }\n" + " resultIsReadOnly = true;\n" + " return result.MakeReadOnly();\n" + "}\n\n"); if (optimize_speed()) { - writer->WriteLine( - "public override Builder MergeFrom(pb::IMessage$0$ other) {", - runtime_suffix()); - writer->WriteLine(" if (other is $0$) {", class_name()); - writer->WriteLine(" return MergeFrom(($0$) other);", class_name()); - writer->WriteLine(" } else {"); - writer->WriteLine(" base.MergeFrom(other);"); - writer->WriteLine(" return this;"); - writer->WriteLine(" }"); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine("public override Builder MergeFrom($0$ other) {", - class_name()); + printer->Print( + vars, + "public override Builder MergeFrom(pb::IMessage$suffix$ other) {\n" + " if (other is $class_name$) {\n" + " return MergeFrom(($class_name$) other);\n" + " } else {\n" + " base.MergeFrom(other);\n" + " return this;\n" + " }\n" + "}\n\n"); + + printer->Print(vars,"public override Builder MergeFrom($class_name$ other) {\n"); // Optimization: If other is the default instance, we know none of its // fields are set so we can skip the merge. - writer->Indent(); - writer->WriteLine("if (other == $0$.DefaultInstance) return this;", - full_class_name()); - writer->WriteLine("PrepareBuilder();"); + printer->Indent(); + printer->Print( + vars, + "if (other == $full_class_name$.DefaultInstance) return this;\n" + "PrepareBuilder();\n"); for (int i = 0; i < descriptor_->field_count(); i++) { if (!descriptor_->field(i)->containing_oneof()) { scoped_ptr<FieldGeneratorBase> generator( CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->GenerateMergingCode(writer); + generator->GenerateMergingCode(printer); } } // Merge oneof fields for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - string name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); - string property_name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); - writer->WriteLine("switch (other.$0$Case) {", property_name); - writer->Indent(); + vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); + vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); + printer->Print(vars, "switch (other.$property_name$Case) {\n"); + printer->Indent(); for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - writer->WriteLine("case $0$OneofCase.$1$: {", - property_name, GetPropertyName(field)); + vars["field_property_name"] = GetPropertyName(field); + printer->Print( + vars, + "case $property_name$OneofCase.$field_property_name$: {\n"); if (field->type() == FieldDescriptor::TYPE_GROUP || field->type() == FieldDescriptor::TYPE_MESSAGE) { - writer->WriteLine(" Merge$0$(other.$0$);", GetPropertyName(field)); + printer->Print( + vars, + " Merge$field_property_name$(other.$field_property_name$);\n"); } else { - writer->WriteLine(" Set$0$(other.$0$);", GetPropertyName(field)); + printer->Print( + vars, + " Set$field_property_name$(other.$field_property_name$);\n"); } - writer->WriteLine(" break;"); - writer->WriteLine("}"); + printer->Print(" break;\n"); + printer->Print("}\n"); } - writer->WriteLine("case $0$OneofCase.None: { break; }", property_name); - writer->Outdent(); - writer->WriteLine("}"); + printer->Print(vars, "case $property_name$OneofCase.None: { break; }\n"); + printer->Outdent(); + printer->Print("}\n"); } // if message type has extensions if (descriptor_->extension_range_count() > 0) { - writer->WriteLine(" this.MergeExtensionFields(other);"); + printer->Print(" this.MergeExtensionFields(other);\n"); } if (!use_lite_runtime()) { - writer->WriteLine("this.MergeUnknownFields(other.UnknownFields);"); + printer->Print("this.MergeUnknownFields(other.UnknownFields);\n"); } - writer->WriteLine("return this;"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Print("return this;\n"); + printer->Outdent(); + printer->Print("}\n\n"); } } -void MessageGenerator::GenerateBuilderParsingMethods(Writer* writer) { - writer->WriteLine( - "public override Builder MergeFrom(pb::ICodedInputStream input) {"); - writer->WriteLine(" return MergeFrom(input, pb::ExtensionRegistry.Empty);"); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine( - "public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {"); - writer->Indent(); - writer->WriteLine("PrepareBuilder();"); +void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { + printer->Print( + "public override Builder MergeFrom(pb::ICodedInputStream input) {\n" + " return MergeFrom(input, pb::ExtensionRegistry.Empty);\n" + "}\n\n"); + + printer->Print( + "public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {\n"); + printer->Indent(); + printer->Print("PrepareBuilder();\n"); if (!use_lite_runtime()) { - writer->WriteLine("pb::UnknownFieldSet.Builder unknownFields = null;"); - } - writer->WriteLine("uint tag;"); - writer->WriteLine("string field_name;"); - writer->WriteLine("while (input.ReadTag(out tag, out field_name)) {"); - writer->Indent(); - writer->WriteLine("if(tag == 0 && field_name != null) {"); - writer->Indent(); + printer->Print("pb::UnknownFieldSet.Builder unknownFields = null;\n"); + } + printer->Print( + "uint tag;\n" + "string field_name;\n" + "while (input.ReadTag(out tag, out field_name)) {\n"); + printer->Indent(); + printer->Print("if(tag == 0 && field_name != null) {\n"); + printer->Indent(); //if you change from StringComparer.Ordinal, the array sort in FieldNames { get; } must also change - writer->WriteLine( - "int field_ordinal = global::System.Array.BinarySearch(_$0$FieldNames, field_name, global::System.StringComparer.Ordinal);", - UnderscoresToCamelCase(class_name(), false)); - writer->WriteLine("if(field_ordinal >= 0)"); - writer->WriteLine(" tag = _$0$FieldTags[field_ordinal];", - UnderscoresToCamelCase(class_name(), false)); - writer->WriteLine("else {"); + printer->Print( + "int field_ordinal = global::System.Array.BinarySearch(_$camel_class_name$FieldNames, field_name, global::System.StringComparer.Ordinal);\n" + "if(field_ordinal >= 0)\n" + " tag = _$camel_class_name$FieldTags[field_ordinal];\n" + "else {\n", + "camel_class_name", UnderscoresToCamelCase(class_name(), false)); if (!use_lite_runtime()) { - writer->WriteLine(" if (unknownFields == null) {"); // First unknown field - create builder now - writer->WriteLine( - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);"); - writer->WriteLine(" }"); - } - writer->WriteLine( - " ParseUnknownField(input, $0$extensionRegistry, tag, field_name);", - use_lite_runtime() ? "" : "unknownFields, "); - writer->WriteLine(" continue;"); - writer->WriteLine("}"); - writer->Outdent(); - writer->WriteLine("}"); - - writer->WriteLine("switch (tag) {"); - writer->Indent(); - writer->WriteLine("case 0: {"); // 0 signals EOF / limit reached - writer->WriteLine(" throw pb::InvalidProtocolBufferException.InvalidTag();"); - writer->WriteLine("}"); - writer->WriteLine("default: {"); - writer->WriteLine(" if (pb::WireFormat.IsEndGroupTag(tag)) {"); + printer->Print( + " if (unknownFields == null) {\n" // First unknown field - create builder now + " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" + " }\n"); + } + printer->Print( + " ParseUnknownField(input, $prefix$extensionRegistry, tag, field_name);\n", + "prefix", use_lite_runtime() ? "" : "unknownFields, "); + printer->Print(" continue;\n"); + printer->Print("}\n"); + printer->Outdent(); + printer->Print("}\n"); + + printer->Print("switch (tag) {\n"); + printer->Indent(); + printer->Print( + "case 0: {\n" // 0 signals EOF / limit reached + " throw pb::InvalidProtocolBufferException.InvalidTag();\n" + "}\n" + "default: {\n" + " if (pb::WireFormat.IsEndGroupTag(tag)) {\n"); if (!use_lite_runtime()) { - writer->WriteLine(" if (unknownFields != null) {"); - writer->WriteLine(" this.UnknownFields = unknownFields.Build();"); - writer->WriteLine(" }"); - } - writer->WriteLine(" return this;"); // it's an endgroup tag - writer->WriteLine(" }"); + printer->Print( + " if (unknownFields != null) {\n" + " this.UnknownFields = unknownFields.Build();\n" + " }\n"); + } + printer->Print( + " return this;\n" // it's an endgroup tag + " }\n"); if (!use_lite_runtime()) { - writer->WriteLine(" if (unknownFields == null) {"); // First unknown field - create builder now - writer->WriteLine( - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);"); - writer->WriteLine(" }"); + printer->Print( + " if (unknownFields == null) {\n" // First unknown field - create builder now + " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" + " }\n"); } - writer->WriteLine( - " ParseUnknownField(input, $0$extensionRegistry, tag, field_name);", - use_lite_runtime() ? "" : "unknownFields, "); - writer->WriteLine(" break;"); - writer->WriteLine("}"); + printer->Print( + " ParseUnknownField(input, $prefix$extensionRegistry, tag, field_name);\n", + "prefix", use_lite_runtime() ? "" : "unknownFields, "); + printer->Print(" break;\n"); + printer->Print("}\n"); for (int i = 0; i < fields_by_number().size(); i++) { const FieldDescriptor* field = fields_by_number()[i]; @@ -853,53 +876,54 @@ void MessageGenerator::GenerateBuilderParsingMethods(Writer* writer) { && (wt == internal::WireFormatLite::WIRETYPE_VARINT || wt == internal::WireFormatLite::WIRETYPE_FIXED32 || wt == internal::WireFormatLite::WIRETYPE_FIXED64)) { - writer->WriteLine( - "case $0$:", - SimpleItoa( - internal::WireFormatLite::MakeTag( - field->number(), - internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED))); + printer->Print( + "case $number$:\n", + "number", + SimpleItoa( + internal::WireFormatLite::MakeTag( + field->number(), + internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED))); } - writer->WriteLine("case $0$: {", SimpleItoa(tag)); - writer->Indent(); + printer->Print("case $tag$: {\n", "tag", SimpleItoa(tag)); + printer->Indent(); scoped_ptr<FieldGeneratorBase> generator( CreateFieldGeneratorInternal(field)); - generator->GenerateParsingCode(writer); - writer->WriteLine("break;"); - writer->Outdent(); - writer->WriteLine("}"); + generator->GenerateParsingCode(printer); + printer->Print("break;\n"); + printer->Outdent(); + printer->Print("}\n"); } - writer->Outdent(); - writer->WriteLine("}"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Outdent(); + printer->Print("}\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("\n"); if (!use_lite_runtime()) { - writer->WriteLine("if (unknownFields != null) {"); - writer->WriteLine(" this.UnknownFields = unknownFields.Build();"); - writer->WriteLine("}"); - } - writer->WriteLine("return this;"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Print( + "if (unknownFields != null) {\n" + " this.UnknownFields = unknownFields.Build();\n" + "}\n"); + } + printer->Print("return this;\n"); + printer->Outdent(); + printer->Print("}\n\n"); } -void MessageGenerator::GenerateIsInitialized(Writer* writer) { - writer->WriteLine("public override bool IsInitialized {"); - writer->Indent(); - writer->WriteLine("get {"); - writer->Indent(); +void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { + printer->Print("public override bool IsInitialized {\n"); + printer->Indent(); + printer->Print("get {\n"); + printer->Indent(); // Check that all required fields in this message are set. // TODO(kenton): We can optimize this when we switch to putting all the // "has" fields into a single bitfield. for (int i = 0; i < descriptor_->field_count(); i++) { if (descriptor_->field(i)->is_required()) { - writer->WriteLine("if (!has$0$) return false;", - GetPropertyName(descriptor_->field(i))); + printer->Print("if (!has$property_name$) return false;\n", + "property_name", GetPropertyName(descriptor_->field(i))); } } @@ -916,43 +940,48 @@ void MessageGenerator::GenerateIsInitialized(Writer* writer) { string propertyName = UnderscoresToPascalCase(GetFieldName(field)); if (field->is_repeated()) { - writer->WriteLine("foreach ($0$ element in $1$List) {", - GetClassName(field->message_type()), - propertyName); - writer->WriteLine(" if (!element.IsInitialized) return false;"); - writer->WriteLine("}"); + printer->Print( + "foreach ($class_name$ element in $property_name$List) {\n" + " if (!element.IsInitialized) return false;\n" + "}\n", + "class_name", GetClassName(field->message_type()), + "property_name", propertyName); } else if (field->is_optional()) { - writer->WriteLine("if (Has$0$) {", propertyName); - writer->WriteLine(" if (!$0$.IsInitialized) return false;", propertyName); - writer->WriteLine("}"); + printer->Print( + "if (Has$property_name$) {\n" + " if (!$property_name$.IsInitialized) return false;\n" + "}\n", + "property_name", propertyName); } else { - writer->WriteLine("if (!$0$.IsInitialized) return false;", propertyName); + printer->Print( + "if (!$property_name$.IsInitialized) return false;\n", + "property_name", propertyName); } } if (descriptor_->extension_range_count() > 0) { - writer->WriteLine("if (!ExtensionsAreInitialized) return false;"); - } - writer->WriteLine("return true;"); - writer->Outdent(); - writer->WriteLine("}"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Print("if (!ExtensionsAreInitialized) return false;\n"); + } + printer->Print("return true;\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("\n"); } -void MessageGenerator::GenerateExtensionRegistrationCode(Writer* writer) { +void MessageGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) { for (int i = 0; i < descriptor_->extension_count(); i++) { ExtensionGenerator extensionGenerator(descriptor_->extension(i)); - extensionGenerator.GenerateExtensionRegistrationCode(writer); + extensionGenerator.GenerateExtensionRegistrationCode(printer); } for (int i = 0; i < descriptor_->nested_type_count(); i++) { MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.GenerateExtensionRegistrationCode(writer); + messageGenerator.GenerateExtensionRegistrationCode(printer); } } diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h index b8d15df0..ebe58618 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.h +++ b/src/google/protobuf/compiler/csharp/csharp_message.h @@ -51,27 +51,27 @@ class MessageGenerator : public SourceGeneratorBase { MessageGenerator(const Descriptor* descriptor); ~MessageGenerator(); - void GenerateStaticVariables(Writer* printer); - void GenerateStaticVariableInitializers(Writer* printer); - void GenerateExtensionRegistrationCode(Writer* printer); - void Generate(Writer* printer); + void GenerateStaticVariables(io::Printer* printer); + void GenerateStaticVariableInitializers(io::Printer* printer); + void GenerateExtensionRegistrationCode(io::Printer* printer); + void Generate(io::Printer* printer); private: const Descriptor* descriptor_; std::vector<std::string> field_names_; std::vector<const FieldDescriptor*> fields_by_number_; - void GenerateLiteRuntimeMethods(Writer* writer); - void GenerateMessageSerializationMethods(Writer* writer); - void GenerateSerializeOneField(Writer* writer, + void GenerateLiteRuntimeMethods(io::Printer* printer); + void GenerateMessageSerializationMethods(io::Printer* printer); + void GenerateSerializeOneField(io::Printer* printer, const FieldDescriptor* fieldDescriptor); void GenerateSerializeOneExtensionRange( - Writer* writer, const Descriptor::ExtensionRange* extendsionRange); - void GenerateParseFromMethods(Writer* writer); - void GenerateBuilder(Writer* writer); - void GenerateCommonBuilderMethods(Writer* writer); - void GenerateBuilderParsingMethods(Writer* writer); - void GenerateIsInitialized(Writer* writer); + io::Printer* printer, const Descriptor::ExtensionRange* extendsionRange); + void GenerateParseFromMethods(io::Printer* printer); + void GenerateBuilder(io::Printer* printer); + void GenerateCommonBuilderMethods(io::Printer* printer); + void GenerateBuilderParsingMethods(io::Printer* printer); + void GenerateIsInitialized(io::Printer* printer); int GetFieldOrdinal(const FieldDescriptor* descriptor); FieldGeneratorBase* CreateFieldGeneratorInternal( diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc index b533d735..50eb9df6 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc @@ -40,7 +40,6 @@ #include <google/protobuf/compiler/csharp/csharp_helpers.h> #include <google/protobuf/compiler/csharp/csharp_message_field.h> -#include <google/protobuf/compiler/csharp/csharp_writer.h> namespace google { namespace protobuf { @@ -50,245 +49,291 @@ namespace csharp { MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { - has_property_check = "has" + property_name(); + variables_["has_property_check"] = "has" + property_name(); + variables_["message_or_group"] = message_or_group(); } MessageFieldGenerator::~MessageFieldGenerator() { } -void MessageFieldGenerator::GenerateMembers(Writer* writer) { - writer->WriteLine("private bool has$0$;", property_name()); - writer->WriteLine("private $0$ $1$_;", type_name(), name()); - AddDeprecatedFlag(writer); - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return has$0$; }", property_name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return $0$_ ?? $1$; }", name(), default_value()); - writer->WriteLine("}"); +void MessageFieldGenerator::GenerateMembers(io::Printer* printer) { + printer->Print( + variables_, + "private bool has$property_name$;\n" + "private $type_name$ $name$_;\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public bool Has$property_name$ {\n" + " get { return has$property_name$; }\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public $type_name$ $property_name$ {\n" + " get { return $name$_ ?? $default_value$; }\n" + "}\n"); } -void MessageFieldGenerator::GenerateBuilderMembers(Writer* writer) { - AddDeprecatedFlag(writer); - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return result.has$0$; }", property_name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return result.$0$; }", property_name()); - writer->WriteLine(" set { Set$0$(value); }", property_name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Set$0$($1$ value) {", property_name(), - type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.has$0$ = true;", property_name()); - writer->WriteLine(" result.$0$_ = value;", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Set$0$($1$.Builder builderForValue) {", - property_name(), type_name()); - AddNullCheck(writer, "builderForValue"); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.has$0$ = true;", property_name()); - writer->WriteLine(" result.$0$_ = builderForValue.Build();", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Merge$0$($1$ value) {", property_name(), - type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" if (result.has$0$ &&", property_name()); - writer->WriteLine(" result.$0$_ != $1$) {", name(), default_value()); - writer->WriteLine( - " result.$0$_ = $1$.CreateBuilder(result.$0$_).MergeFrom(value).BuildPartial();", - name(), type_name()); - writer->WriteLine(" } else {"); - writer->WriteLine(" result.$0$_ = value;", name()); - writer->WriteLine(" }"); - writer->WriteLine(" result.has$0$ = true;", property_name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Clear$0$() {", property_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.has$0$ = false;", property_name()); - writer->WriteLine(" result.$0$_ = null;", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); +void MessageFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public bool Has$property_name$ {\n" + " get { return result.has$property_name$; }\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public $type_name$ $property_name$ {\n" + " get { return result.$property_name$; }\n" + " set { Set$property_name$(value); }\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Set$property_name$($type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.has$property_name$ = true;\n" + " result.$name$_ = value;\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Set$property_name$($type_name$.Builder builderForValue) {\n"); + AddNullCheck(printer, "builderForValue"); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.has$property_name$ = true;\n" + " result.$name$_ = builderForValue.Build();\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Merge$property_name$($type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print( + variables_, + " PrepareBuilder();\n" + " if (result.has$property_name$ &&\n" + " result.$name$_ != $default_value$) {\n" + " result.$name$_ = $type_name$.CreateBuilder(result.$name$_).MergeFrom(value).BuildPartial();\n" + " } else {\n" + " result.$name$_ = value;\n" + " }\n" + " result.has$property_name$ = true;\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Clear$property_name$() {\n" + " PrepareBuilder();\n" + " result.has$property_name$ = false;\n" + " result.$name$_ = null;\n" + " return this;\n" + "}\n"); } -void MessageFieldGenerator::GenerateMergingCode(Writer* writer) { - writer->WriteLine("if (other.Has$0$) {", property_name()); - writer->WriteLine(" Merge$0$(other.$0$);", property_name()); - writer->WriteLine("}"); +void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { + printer->Print( + variables_, + "if (other.Has$property_name$) {\n" + " Merge$property_name$(other.$property_name$);\n" + "}\n"); } -void MessageFieldGenerator::GenerateBuildingCode(Writer* writer) { +void MessageFieldGenerator::GenerateBuildingCode(io::Printer* printer) { // Nothing to do for singular fields } -void MessageFieldGenerator::GenerateParsingCode(Writer* writer) { - writer->WriteLine("$0$.Builder subBuilder = $0$.CreateBuilder();", - type_name()); - writer->WriteLine("if (result.has$0$) {", property_name()); - writer->WriteLine(" subBuilder.MergeFrom($0$);", property_name()); - writer->WriteLine("}"); +void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "$type_name$.Builder subBuilder = $type_name$.CreateBuilder();\n" + "if (result.has$property_name$) {\n" + " subBuilder.MergeFrom($property_name$);\n" + "}\n"); if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { - writer->WriteLine("input.ReadGroup($0$, subBuilder, extensionRegistry);", - number()); + printer->Print( + variables_, + "input.ReadGroup($number$, subBuilder, extensionRegistry);\n"); } else { - writer->WriteLine("input.ReadMessage(subBuilder, extensionRegistry);"); + printer->Print("input.ReadMessage(subBuilder, extensionRegistry);\n"); } - writer->WriteLine("$0$ = subBuilder.BuildPartial();", property_name()); + printer->Print( + variables_, + "$property_name$ = subBuilder.BuildPartial();\n"); } -void MessageFieldGenerator::GenerateSerializationCode(Writer* writer) { - writer->WriteLine("if ($0$) {", has_property_check); - writer->WriteLine(" output.Write$0$($1$, field_names[$3$], $2$);", - message_or_group(), number(), property_name(), - field_ordinal()); - writer->WriteLine("}"); +void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " output.Write$message_or_group$($number$, field_names[$field_ordinal$], $property_name$);\n" + "}\n"); } -void MessageFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { - writer->WriteLine("if ($0$) {", has_property_check); - writer->WriteLine(" size += pb::CodedOutputStream.Compute$0$Size($1$, $2$);", - message_or_group(), number(), property_name()); - writer->WriteLine("}"); +void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " size += pb::CodedOutputStream.Compute$message_or_group$Size($number$, $property_name$);\n" + "}\n"); } -void MessageFieldGenerator::WriteHash(Writer* writer) { - writer->WriteLine("if (has$0$) hash ^= $1$_.GetHashCode();", property_name(), - name()); +void MessageFieldGenerator::WriteHash(io::Printer* printer) { + printer->Print( + variables_, + "if (has$property_name$) hash ^= $name$_.GetHashCode();\n"); } -void MessageFieldGenerator::WriteEquals(Writer* writer) { - writer->WriteLine( - "if (has$0$ != other.has$0$ || (has$0$ && !$1$_.Equals(other.$1$_))) return false;", - property_name(), name()); +void MessageFieldGenerator::WriteEquals(io::Printer* printer) { + printer->Print( + variables_, + "if (has$property_name$ != other.has$property_name$ || (has$property_name$ && !$name$_.Equals(other.$name$_))) return false;\n"); } -void MessageFieldGenerator::WriteToString(Writer* writer) { - writer->WriteLine("PrintField(\"$2$\", has$0$, $1$_, writer);", - property_name(), name(), GetFieldName(descriptor_)); +void MessageFieldGenerator::WriteToString(io::Printer* printer) { + variables_["field_name"] = GetFieldName(descriptor_); + printer->Print( + variables_, + "PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n"); } MessageOneofFieldGenerator::MessageOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal) : MessageFieldGenerator(descriptor, fieldOrdinal) { - has_property_check = oneof_name() + "Case_ == " + oneof_property_name() + - "OneofCase." + property_name(); + SetCommonOneofFieldVariables(&variables_); } MessageOneofFieldGenerator::~MessageOneofFieldGenerator() { } -void MessageOneofFieldGenerator::GenerateMembers(Writer* writer) { +void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) { if (SupportFieldPresence(descriptor_->file())) { - AddDeprecatedFlag(writer); - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return $0$; }", has_property_check); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public bool Has$property_name$ {\n" + " get { return $has_property_check$; }\n" + "}\n"); } - AddDeprecatedFlag(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return $0$ ? ($1$) $2$_ : $3$; }", - has_property_check, type_name(), oneof_name(), default_value()); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public $type_name$ $property_name$ {\n" + " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n" + "}\n"); } -void MessageOneofFieldGenerator::GenerateBuilderMembers(Writer* writer) { +void MessageOneofFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { if (SupportFieldPresence(descriptor_->file())) { - AddDeprecatedFlag(writer); - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return result.$0$; }", has_property_check); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public bool Has$property_name$ {\n" + " get { return result.$has_property_check$; }\n" + "}\n"); } - AddDeprecatedFlag(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return result.$0$ ? ($1$) result.$2$_ : $3$; }", - has_property_check, type_name(), oneof_name(), default_value()); - writer->WriteLine(" set { Set$0$(value); }", property_name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Set$0$($1$ value) {", property_name(), - type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", - oneof_name(), oneof_property_name(), property_name()); - writer->WriteLine(" result.$0$_ = value;", oneof_name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Set$0$($1$.Builder builderForValue) {", - property_name(), type_name()); - AddNullCheck(writer, "builderForValue"); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", - oneof_name(), oneof_property_name(), property_name()); - writer->WriteLine(" result.$0$_ = builderForValue.Build();", oneof_name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Merge$0$($1$ value) {", property_name(), - type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" if (result.$0$ &&", has_property_check); - writer->WriteLine(" result.$0$ != $1$) {", property_name(), default_value()); - writer->WriteLine( - " result.$0$_ = $1$.CreateBuilder(result.$2$).MergeFrom(value).BuildPartial();", - oneof_name(), type_name(), property_name()); - writer->WriteLine(" } else {"); - writer->WriteLine(" result.$0$_ = value;", oneof_name()); - writer->WriteLine(" }"); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", - oneof_name(), oneof_property_name(), property_name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Clear$0$() {", property_name()); - writer->WriteLine(" if (result.$0$) {", has_property_check); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.None;", - oneof_name(), oneof_property_name()); - writer->WriteLine(" result.$0$_ = null;", oneof_name()); - writer->WriteLine(" }"); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public $type_name$ $property_name$ {\n" + " get { return result.$has_property_check$ ? ($type_name$) result.$oneof_name$_ : $default_value$; }\n" + " set { Set$property_name$(value); }\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Set$property_name$($type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + " result.$oneof_name$_ = value;\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Set$property_name$($type_name$.Builder builderForValue) {\n"); + AddNullCheck(printer, "builderForValue"); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + " result.$oneof_name$_ = builderForValue.Build();\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Merge$property_name$($type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print( + variables_, + " PrepareBuilder();\n" + " if (result.$has_property_check$ &&\n" + " result.$property_name$ != $default_value$) {\n" + " result.$oneof_name$_ = $type_name$.CreateBuilder(result.$property_name$).MergeFrom(value).BuildPartial();\n" + " } else {\n" + " result.$oneof_name$_ = value;\n" + " }\n" + " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Clear$property_name$() {\n" + " if (result.$has_property_check$) {\n" + " PrepareBuilder();\n" + " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.None;\n" + " result.$oneof_name$_ = null;\n" + " }\n" + " return this;\n" + "}\n"); } -void MessageOneofFieldGenerator::GenerateParsingCode(Writer* writer) { - writer->WriteLine("$0$.Builder subBuilder = $0$.CreateBuilder();", - type_name()); - writer->WriteLine("if (result.$0$) {", has_property_check); - writer->WriteLine(" subBuilder.MergeFrom($0$);", property_name()); - writer->WriteLine("}"); +void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "$type_name$.Builder subBuilder = $type_name$.CreateBuilder();\n" + "if (result.$has_property_check$) {\n" + " subBuilder.MergeFrom($property_name$);\n" + "}\n"); if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { - writer->WriteLine("input.ReadGroup($0$, subBuilder, extensionRegistry);", - number()); + printer->Print( + variables_, + "input.ReadGroup($number$, subBuilder, extensionRegistry);\n"); } else { - writer->WriteLine("input.ReadMessage(subBuilder, extensionRegistry);"); + printer->Print("input.ReadMessage(subBuilder, extensionRegistry);\n"); } - writer->WriteLine("result.$0$_ = subBuilder.BuildPartial();", oneof_name()); - writer->WriteLine("result.$0$Case_ = $1$OneofCase.$2$;", - oneof_name(), oneof_property_name(), property_name()); + printer->Print( + variables_, + "result.$oneof_name$_ = subBuilder.BuildPartial();\n" + "result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"); } -void MessageOneofFieldGenerator::WriteEquals(Writer* writer) { - writer->WriteLine("if (!$0$.Equals(other.$0$)) return false;", property_name()); +void MessageOneofFieldGenerator::WriteEquals(io::Printer* printer) { + printer->Print( + variables_, + "if (!$property_name$.Equals(other.$property_name$)) return false;\n"); } -void MessageOneofFieldGenerator::WriteToString(Writer* writer) { - writer->WriteLine("PrintField(\"$0$\", $1$, $2$_, writer);", - descriptor_->name(), has_property_check, oneof_name()); +void MessageOneofFieldGenerator::WriteToString(io::Printer* printer) { + printer->Print( + variables_, + "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.h b/src/google/protobuf/compiler/csharp/csharp_message_field.h index d455ade5..d820908c 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.h @@ -48,20 +48,17 @@ class MessageFieldGenerator : public FieldGeneratorBase { MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~MessageFieldGenerator(); - virtual void GenerateMembers(Writer* writer); - virtual void GenerateBuilderMembers(Writer* writer); - virtual void GenerateMergingCode(Writer* writer); - virtual void GenerateBuildingCode(Writer* writer); - virtual void GenerateParsingCode(Writer* writer); - virtual void GenerateSerializationCode(Writer* writer); - virtual void GenerateSerializedSizeCode(Writer* writer); - - virtual void WriteHash(Writer* writer); - virtual void WriteEquals(Writer* writer); - virtual void WriteToString(Writer* writer); - - protected: - string has_property_check; + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateBuilderMembers(io::Printer* printer); + virtual void GenerateMergingCode(io::Printer* printer); + virtual void GenerateBuildingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); + + virtual void WriteHash(io::Printer* printer); + virtual void WriteEquals(io::Printer* printer); + virtual void WriteToString(io::Printer* printer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); @@ -72,11 +69,11 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator { MessageOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~MessageOneofFieldGenerator(); - virtual void GenerateMembers(Writer* writer); - virtual void GenerateBuilderMembers(Writer* writer); - virtual void WriteEquals(Writer* writer); - virtual void WriteToString(Writer* writer); - virtual void GenerateParsingCode(Writer* writer); + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateBuilderMembers(io::Printer* printer); + virtual void WriteEquals(io::Printer* printer); + virtual void WriteToString(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator); diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index a54edfe3..652eb6b9 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -40,7 +40,6 @@ #include <google/protobuf/compiler/csharp/csharp_helpers.h> #include <google/protobuf/compiler/csharp/csharp_primitive_field.h> -#include <google/protobuf/compiler/csharp/csharp_writer.h> namespace google { namespace protobuf { @@ -50,202 +49,232 @@ namespace csharp { PrimitiveFieldGenerator::PrimitiveFieldGenerator( const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { - if (SupportFieldPresence(descriptor_->file())) { - has_property_check = "has" + property_name(); - } else { - has_property_check = property_name() + " != " + default_value(); - } } PrimitiveFieldGenerator::~PrimitiveFieldGenerator() { } -void PrimitiveFieldGenerator::GenerateMembers(Writer* writer) { +void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("private bool has$0$;", property_name()); + printer->Print(variables_, "private bool has$property_name$;\n"); } - writer->WriteLine("private $0$ $1$_$2$;", type_name(), name(), - has_default_value() ? " = " + default_value() : ""); - AddDeprecatedFlag(writer); + printer->Print( + variables_, + "private $type_name$ $name_def_message$;\n"); + AddDeprecatedFlag(printer); if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return has$0$; }", property_name()); - writer->WriteLine("}"); + printer->Print( + variables_, + "public bool Has$property_name$ {\n" + " get { return has$property_name$; }\n" + "}\n"); } - AddPublicMemberAttributes(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return $0$_; }", name()); - writer->WriteLine("}"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public $type_name$ $property_name$ {\n" + " get { return $name$_; }\n" + "}\n"); } -void PrimitiveFieldGenerator::GenerateBuilderMembers(Writer* writer) { - AddDeprecatedFlag(writer); +void PrimitiveFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { + AddDeprecatedFlag(printer); if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return result.has$0$; }", property_name()); - writer->WriteLine("}"); + printer->Print( + variables_, + "public bool Has$property_name$ {\n" + " get { return result.has$property_name$; }\n" + "}\n"); } - AddPublicMemberAttributes(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return result.$0$; }", property_name()); - writer->WriteLine(" set { Set$0$(value); }", property_name()); - writer->WriteLine("}"); - AddPublicMemberAttributes(writer); - writer->WriteLine("public Builder Set$0$($1$ value) {", property_name(), - type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public $type_name$ $property_name$ {\n" + " get { return result.$property_name$; }\n" + " set { Set$property_name$(value); }\n" + "}\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public Builder Set$property_name$($type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print(" PrepareBuilder();\n"); if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine(" result.has$0$ = true;", property_name()); + printer->Print( + variables_, + " result.has$property_name$ = true;\n"); } - writer->WriteLine(" result.$0$_ = value;", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Clear$0$() {", property_name()); - writer->WriteLine(" PrepareBuilder();"); + printer->Print( + variables_, + " result.$name$_ = value;\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Clear$property_name$() {\n" + " PrepareBuilder();\n"); if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine(" result.has$0$ = false;", property_name()); + printer->Print( + variables_, + " result.has$property_name$ = false;\n"); } - writer->WriteLine(" result.$0$_ = $1$;", name(), default_value()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); + printer->Print( + variables_, + " result.$name$_ = $default_value$;\n" + " return this;\n" + "}\n"); } -void PrimitiveFieldGenerator::GenerateMergingCode(Writer* writer) { - if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("if (other.Has$0$) {", property_name()); - } else { - writer->WriteLine("if (other.$0$ != $1$) {", property_name(), default_value()); - } - writer->WriteLine(" $0$ = other.$0$;", property_name()); - writer->WriteLine("}"); +void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($other_has_property_check$) {\n" + " $property_name$ = other.$property_name$;\n" + "}\n"); } -void PrimitiveFieldGenerator::GenerateBuildingCode(Writer* writer) { +void PrimitiveFieldGenerator::GenerateBuildingCode(io::Printer* printer) { // Nothing to do here for primitive types } -void PrimitiveFieldGenerator::GenerateParsingCode(Writer* writer) { +void PrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) { if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("result.has$0$ = input.Read$1$(ref result.$2$_);", - property_name(), capitalized_type_name(), name()); + printer->Print( + variables_, + "result.has$property_name$ = input.Read$capitalized_type_name$(ref result.$name$_);\n"); } else { - writer->WriteLine("input.Read$0$(ref result.$1$_);", - capitalized_type_name(), name()); + printer->Print( + variables_, + "input.Read$capitalized_type_name$(ref result.$name$_);\n"); } } -void PrimitiveFieldGenerator::GenerateSerializationCode(Writer* writer) { - writer->WriteLine("if ($0$) {", has_property_check); - writer->WriteLine(" output.Write$0$($1$, field_names[$3$], $2$);", - capitalized_type_name(), number(), property_name(), - field_ordinal()); - writer->WriteLine("}"); +void PrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " output.Write$capitalized_type_name$($number$, field_names[$field_ordinal$], $property_name$);\n" + "}\n"); } -void PrimitiveFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { - writer->WriteLine("if ($0$) {", has_property_check); - writer->WriteLine(" size += pb::CodedOutputStream.Compute$0$Size($1$, $2$);", - capitalized_type_name(), number(), property_name()); - writer->WriteLine("}"); +void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " size += pb::CodedOutputStream.Compute$capitalized_type_name$Size($number$, $property_name$);\n" + "}\n"); } -void PrimitiveFieldGenerator::WriteHash(Writer* writer) { - writer->WriteLine("if ($0$) {", has_property_check); - writer->WriteLine(" hash ^= $0$_.GetHashCode();", name()); - writer->WriteLine("}"); +void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " hash ^= $name$_.GetHashCode();\n" + "}\n"); } -void PrimitiveFieldGenerator::WriteEquals(Writer* writer) { +void PrimitiveFieldGenerator::WriteEquals(io::Printer* printer) { if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine( - "if (has$0$ != other.has$0$ || (has$0$ && !$1$_.Equals(other.$1$_))) return false;", - property_name(), name()); + printer->Print( + variables_, + "if (has$property_name$ != other.has$property_name$ || (has$property_name$ && !$name$_.Equals(other.$name$_))) return false;\n"); } else { - writer->WriteLine( - "if (!$0$_.Equals(other.$0$_)) return false;", name()); + printer->Print( + variables_, + "if (!$name$_.Equals(other.$name$_)) return false;\n"); } } -void PrimitiveFieldGenerator::WriteToString(Writer* writer) { - writer->WriteLine("PrintField(\"$0$\", $1$, $2$_, writer);", - descriptor_->name(), has_property_check, name()); +void PrimitiveFieldGenerator::WriteToString(io::Printer* printer) { + printer->Print( + variables_, + "PrintField(\"$descriptor_name$\", $has_property_check$, $name$_, writer);\n"); } PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator( const FieldDescriptor* descriptor, int fieldOrdinal) : PrimitiveFieldGenerator(descriptor, fieldOrdinal) { - has_property_check = oneof_name() + "Case_ == " + oneof_property_name() + - "OneofCase." + property_name(); + SetCommonOneofFieldVariables(&variables_); } PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() { } -void PrimitiveOneofFieldGenerator::GenerateMembers(Writer* writer) { - AddDeprecatedFlag(writer); +void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) { + AddDeprecatedFlag(printer); if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return $0$; }", has_property_check); - writer->WriteLine("}"); + printer->Print( + variables_, + "public bool Has$property_name$ {\n" + " get { return $has_property_check$; }\n" + "}\n"); } - AddPublicMemberAttributes(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return $0$ ? ($1$) $2$_ : $3$; }", - has_property_check, type_name(), oneof_name(), default_value()); - writer->WriteLine("}"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public $type_name$ $property_name$ {\n" + " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n" + "}\n"); } -void PrimitiveOneofFieldGenerator::GenerateBuilderMembers(Writer* writer) { - AddDeprecatedFlag(writer); +void PrimitiveOneofFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { + AddDeprecatedFlag(printer); if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return result.$0$; }", has_property_check); - writer->WriteLine("}"); + printer->Print( + variables_, + "public bool Has$property_name$ {\n" + " get { return result.$has_property_check$; }\n" + "}\n"); } - AddPublicMemberAttributes(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return result.$0$ ? ($1$) result.$2$_ : $3$; }", - has_property_check, type_name(), oneof_name(), default_value()); - writer->WriteLine(" set { Set$0$(value); }", property_name()); - writer->WriteLine("}"); - AddPublicMemberAttributes(writer); - writer->WriteLine("public Builder Set$0$($1$ value) {", property_name(), - type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_ = value;", oneof_name()); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", - oneof_name(), oneof_property_name(), property_name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Clear$0$() {", property_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" if (result.$0$) {", has_property_check); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.None;", - oneof_name(), oneof_property_name()); - writer->WriteLine(" }"); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); -} - -void PrimitiveOneofFieldGenerator::WriteEquals(Writer* writer) { - writer->WriteLine("if (!$0$.Equals(other.$0$)) return false;", property_name()); -} -void PrimitiveOneofFieldGenerator::WriteToString(Writer* writer) { - writer->WriteLine("PrintField(\"$0$\", $1$, $2$_, writer);", - descriptor_->name(), has_property_check, oneof_name()); -} - -void PrimitiveOneofFieldGenerator::GenerateParsingCode(Writer* writer) { - writer->WriteLine("$0$ value = $1$;", type_name(), default_value()); - writer->WriteLine("if (input.Read$0$(ref value)) {", - capitalized_type_name()); - writer->WriteLine(" result.$0$_ = value;", oneof_name()); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", - oneof_name(), oneof_property_name(), property_name()); - writer->WriteLine("}"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public $type_name$ $property_name$ {\n" + " get { return result.$has_property_check$ ? ($type_name$) result.$oneof_name$_ : $default_value$; }\n" + " set { Set$property_name$(value); }\n" + "}\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public Builder Set$property_name$($type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$oneof_name$_ = value;\n" + " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Clear$property_name$() {\n" + " PrepareBuilder();\n" + " if (result.$has_property_check$) {\n" + " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.None;\n" + " }\n" + " return this;\n" + "}\n"); +} + +void PrimitiveOneofFieldGenerator::WriteEquals(io::Printer* printer) { + printer->Print( + variables_, + "if (!$property_name$.Equals(other.$property_name$)) return false;\n"); +} +void PrimitiveOneofFieldGenerator::WriteToString(io::Printer* printer) { + printer->Print(variables_, + "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n"); +} + +void PrimitiveOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "$type_name$ value = $default_value$;\n" + "if (input.Read$capitalized_type_name$(ref value)) {\n" + " result.$oneof_name$_ = value;\n" + " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + "}\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h index ecc6ed91..8a2d5020 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h @@ -48,20 +48,17 @@ class PrimitiveFieldGenerator : public FieldGeneratorBase { PrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~PrimitiveFieldGenerator(); - virtual void GenerateMembers(Writer* writer); - virtual void GenerateBuilderMembers(Writer* writer); - virtual void GenerateMergingCode(Writer* writer); - virtual void GenerateBuildingCode(Writer* writer); - virtual void GenerateParsingCode(Writer* writer); - virtual void GenerateSerializationCode(Writer* writer); - virtual void GenerateSerializedSizeCode(Writer* writer); - - virtual void WriteHash(Writer* writer); - virtual void WriteEquals(Writer* writer); - virtual void WriteToString(Writer* writer); - - protected: - string has_property_check; + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateBuilderMembers(io::Printer* printer); + virtual void GenerateMergingCode(io::Printer* printer); + virtual void GenerateBuildingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); + + virtual void WriteHash(io::Printer* printer); + virtual void WriteEquals(io::Printer* printer); + virtual void WriteToString(io::Printer* printer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); @@ -72,11 +69,11 @@ class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator { PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~PrimitiveOneofFieldGenerator(); - virtual void GenerateMembers(Writer* writer); - virtual void GenerateBuilderMembers(Writer* writer); - virtual void WriteEquals(Writer* writer); - virtual void WriteToString(Writer* writer); - virtual void GenerateParsingCode(Writer* writer); + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateBuilderMembers(io::Printer* printer); + virtual void WriteEquals(io::Printer* printer); + virtual void WriteToString(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc index cc8745ae..f5ebcfb1 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -40,7 +40,6 @@ #include <google/protobuf/compiler/csharp/csharp_helpers.h> #include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h> -#include <google/protobuf/compiler/csharp/csharp_writer.h> namespace google { namespace protobuf { @@ -56,168 +55,193 @@ RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() { } -void RepeatedEnumFieldGenerator::GenerateMembers(Writer* writer) { +void RepeatedEnumFieldGenerator::GenerateMembers(io::Printer* printer) { if (descriptor_->is_packed() && optimize_speed()) { - writer->WriteLine("private int $0$MemoizedSerializedSize;", name()); + printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n"); } - writer->WriteLine( - "private pbc::PopsicleList<$0$> $1$_ = new pbc::PopsicleList<$0$>();", - type_name(), name()); - AddDeprecatedFlag(writer); - writer->WriteLine("public scg::IList<$0$> $1$List {", type_name(), - property_name()); - writer->WriteLine(" get { return pbc::Lists.AsReadOnly($0$_); }", name()); - writer->WriteLine("}"); + printer->Print(variables_, + "private pbc::PopsicleList<$type_name$> $name$_ = new pbc::PopsicleList<$type_name$>();\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public scg::IList<$type_name$> $property_name$List {\n" + " get { return pbc::Lists.AsReadOnly($name$_); }\n" + "}\n"); // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option. - AddDeprecatedFlag(writer); - writer->WriteLine("public int $0$Count {", property_name()); - writer->WriteLine(" get { return $0$_.Count; }", name()); - writer->WriteLine("}"); - - AddDeprecatedFlag(writer); - writer->WriteLine("public $0$ Get$1$(int index) {", type_name(), - property_name()); - writer->WriteLine(" return $0$_[index];", name()); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public int $property_name$Count {\n" + " get { return $name$_.Count; }\n" + "}\n"); + + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public $type_name$ Get$property_name$(int index) {\n" + " return $name$_[index];\n" + "}\n"); } -void RepeatedEnumFieldGenerator::GenerateBuilderMembers(Writer* writer) { +void RepeatedEnumFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { // Note: We can return the original list here, because we make it unmodifiable when we build // We return it via IPopsicleList so that collection initializers work more pleasantly. - AddDeprecatedFlag(writer); - writer->WriteLine("public pbc::IPopsicleList<$0$> $1$List {", type_name(), - property_name()); - writer->WriteLine(" get { return PrepareBuilder().$0$_; }", name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public int $0$Count {", property_name()); - writer->WriteLine(" get { return result.$0$Count; }", property_name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public $0$ Get$1$(int index) {", type_name(), - property_name()); - writer->WriteLine(" return result.Get$0$(index);", property_name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Set$0$(int index, $1$ value) {", - property_name(), type_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_[index] = value;", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Add$0$($1$ value) {", property_name(), - type_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Add(value);", name(), type_name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine( - "public Builder AddRange$0$(scg::IEnumerable<$1$> values) {", - property_name(), type_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Add(values);", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Clear$0$() {", property_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Clear();", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public pbc::IPopsicleList<$type_name$> $property_name$List {\n" + " get { return PrepareBuilder().$name$_; }\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public int $property_name$Count {\n" + " get { return result.$property_name$Count; }\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public $type_name$ Get$property_name$(int index) {\n" + " return result.Get$property_name$(index);\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Set$property_name$(int index, $type_name$ value) {\n"); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$name$_[index] = value;\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print(variables_, + "public Builder Add$property_name$($type_name$ value) {\n"); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$name$_.Add(value);\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder AddRange$property_name$(scg::IEnumerable<$type_name$> values) {\n" + " PrepareBuilder();\n" + " result.$name$_.Add(values);\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Clear$property_name$() {\n" + " PrepareBuilder();\n" + " result.$name$_.Clear();\n" + " return this;\n" + "}\n"); } -void RepeatedEnumFieldGenerator::GenerateMergingCode(Writer* writer) { - writer->WriteLine("if (other.$0$_.Count != 0) {", name()); - writer->WriteLine(" result.$0$_.Add(other.$0$_);", name()); - writer->WriteLine("}"); +void RepeatedEnumFieldGenerator::GenerateMergingCode(io::Printer* printer) { + printer->Print( + variables_, + "if (other.$name$_.Count != 0) {\n" + " result.$name$_.Add(other.$name$_);\n" + "}\n"); } -void RepeatedEnumFieldGenerator::GenerateBuildingCode(Writer* writer) { - writer->WriteLine("$0$_.MakeReadOnly();", name()); +void RepeatedEnumFieldGenerator::GenerateBuildingCode(io::Printer* printer) { + printer->Print(variables_, "$name$_.MakeReadOnly();\n"); } -void RepeatedEnumFieldGenerator::GenerateParsingCode(Writer* writer) { - writer->WriteLine("scg::ICollection<object> unknownItems;"); - writer->WriteLine( - "input.ReadEnumArray<$0$>(tag, field_name, result.$1$_, out unknownItems);", - type_name(), name()); +void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "scg::ICollection<object> unknownItems;\n" + "input.ReadEnumArray<$type_name$>(tag, field_name, result.$name$_, out unknownItems);\n"); if (!use_lite_runtime()) { - writer->WriteLine("if (unknownItems != null) {"); - writer->WriteLine(" if (unknownFields == null) {"); - writer->WriteLine( - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);"); - writer->WriteLine(" }"); - writer->WriteLine(" foreach (object rawValue in unknownItems)"); - writer->WriteLine(" if (rawValue is int)"); - writer->WriteLine( - " unknownFields.MergeVarintField($0$, (ulong)(int)rawValue);", - number()); - writer->WriteLine("}"); + printer->Print( + variables_, + "if (unknownItems != null) {\n" + " if (unknownFields == null) {\n" + " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" + " }\n" + " foreach (object rawValue in unknownItems)\n" + " if (rawValue is int)\n" + " unknownFields.MergeVarintField($number$, (ulong)(int)rawValue);\n" + "}\n"); } } -void RepeatedEnumFieldGenerator::GenerateSerializationCode(Writer* writer) { - writer->WriteLine("if ($0$_.Count > 0) {", name()); - writer->Indent(); +void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + printer->Print(variables_, "if ($name$_.Count > 0) {\n"); + printer->Indent(); if (descriptor_->is_packed()) { - writer->WriteLine( - "output.WritePackedEnumArray($0$, field_names[$2$], $1$MemoizedSerializedSize, $1$_);", - number(), name(), field_ordinal()); + printer->Print( + variables_, + "output.WritePackedEnumArray($number$, field_names[$field_ordinal$], $name$MemoizedSerializedSize, $name$_);\n"); } else { - writer->WriteLine("output.WriteEnumArray($0$, field_names[$2$], $1$_);", - number(), name(), field_ordinal()); + printer->Print(variables_, + "output.WriteEnumArray($number$, field_names[$field_ordinal$], $name$_);\n"); } - writer->Outdent(); - writer->WriteLine("}"); + printer->Outdent(); + printer->Print("}\n"); } -void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { - writer->WriteLine("{"); - writer->Indent(); - writer->WriteLine("int dataSize = 0;"); - writer->WriteLine("if ($0$_.Count > 0) {", name()); - writer->Indent(); - writer->WriteLine("foreach ($0$ element in $1$_) {", type_name(), name()); - writer->WriteLine( - " dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);"); - writer->WriteLine("}"); - writer->WriteLine("size += dataSize;"); +void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + printer->Print("{\n"); + printer->Indent(); + printer->Print( + variables_, + "int dataSize = 0;\n" + "if ($name$_.Count > 0) {\n"); + printer->Indent(); + printer->Print( + variables_, + "foreach ($type_name$ element in $name$_) {\n" + " dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);\n" + "}\n" + "size += dataSize;\n"); int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); if (descriptor_->is_packed()) { - writer->WriteLine("size += $0$;", SimpleItoa(tagSize)); - writer->WriteLine( - "size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);"); + printer->Print( + "size += $tag_size$;\n" + "size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);\n", + "tag_size", SimpleItoa(tagSize)); } else { - writer->WriteLine("size += $0$ * $1$_.Count;", SimpleItoa(tagSize), name()); + printer->Print( + "size += $tag_size$ * $name$_.Count;\n", + "tag_size", SimpleItoa(tagSize), "name", name()); } - writer->Outdent(); - writer->WriteLine("}"); + printer->Outdent(); + printer->Print("}\n"); // cache the data size for packed fields. if (descriptor_->is_packed()) { - writer->WriteLine("$0$MemoizedSerializedSize = dataSize;", name()); + printer->Print(variables_, + "$name$MemoizedSerializedSize = dataSize;\n"); } - writer->Outdent(); - writer->WriteLine("}"); + printer->Outdent(); + printer->Print("}\n"); } -void RepeatedEnumFieldGenerator::WriteHash(Writer* writer) { - writer->WriteLine("foreach($0$ i in $1$_)", type_name(), name()); - writer->WriteLine(" hash ^= i.GetHashCode();"); +void RepeatedEnumFieldGenerator::WriteHash(io::Printer* printer) { + printer->Print( + variables_, + "foreach($type_name$ i in $name$_)\n" + " hash ^= i.GetHashCode();\n"); } -void RepeatedEnumFieldGenerator::WriteEquals(Writer* writer) { - writer->WriteLine("if($0$_.Count != other.$0$_.Count) return false;", name()); - writer->WriteLine("for(int ix=0; ix < $0$_.Count; ix++)", name()); - writer->WriteLine(" if(!$0$_[ix].Equals(other.$0$_[ix])) return false;", - name()); +void RepeatedEnumFieldGenerator::WriteEquals(io::Printer* printer) { + printer->Print( + variables_, + "if($name$_.Count != other.$name$_.Count) return false;\n" + "for(int ix=0; ix < $name$_.Count; ix++)\n" + " if(!$name$_[ix].Equals(other.$name$_[ix])) return false;\n"); } -void RepeatedEnumFieldGenerator::WriteToString(Writer* writer) { - writer->WriteLine("PrintField(\"$0$\", $1$_, writer);", descriptor_->name(), - name()); +void RepeatedEnumFieldGenerator::WriteToString(io::Printer* printer) { + printer->Print(variables_, + "PrintField(\"$descriptor_name$\", $name$_, writer);\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h index c872131c..68c3d6c9 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h @@ -48,17 +48,17 @@ class RepeatedEnumFieldGenerator : public FieldGeneratorBase { RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~RepeatedEnumFieldGenerator(); - virtual void GenerateMembers(Writer* writer); - virtual void GenerateBuilderMembers(Writer* writer); - virtual void GenerateMergingCode(Writer* writer); - virtual void GenerateBuildingCode(Writer* writer); - virtual void GenerateParsingCode(Writer* writer); - virtual void GenerateSerializationCode(Writer* writer); - virtual void GenerateSerializedSizeCode(Writer* writer); + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateBuilderMembers(io::Printer* printer); + virtual void GenerateMergingCode(io::Printer* printer); + virtual void GenerateBuildingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); - virtual void WriteHash(Writer* writer); - virtual void WriteEquals(Writer* writer); - virtual void WriteToString(Writer* writer); + virtual void WriteHash(io::Printer* printer); + virtual void WriteEquals(io::Printer* printer); + virtual void WriteToString(io::Printer* printer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc index 2dfcd402..2ae1d579 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc @@ -39,7 +39,6 @@ #include <google/protobuf/compiler/csharp/csharp_helpers.h> #include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h> -#include <google/protobuf/compiler/csharp/csharp_writer.h> namespace google { namespace protobuf { @@ -49,150 +48,177 @@ namespace csharp { RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { + variables_["message_or_group"] = message_or_group(); } RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() { } -void RepeatedMessageFieldGenerator::GenerateMembers(Writer* writer) { - writer->WriteLine( - "private pbc::PopsicleList<$0$> $1$_ = new pbc::PopsicleList<$0$>();", - type_name(), name()); - AddDeprecatedFlag(writer); - writer->WriteLine("public scg::IList<$0$> $1$List {", type_name(), - property_name()); - writer->WriteLine(" get { return $0$_; }", name()); - writer->WriteLine("}"); +void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) { + printer->Print( + variables_, + "private pbc::PopsicleList<$type_name$> $name$_ = new pbc::PopsicleList<$type_name$>();\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public scg::IList<$type_name$> $property_name$List {\n" + " get { return $name$_; }\n" + "}\n"); // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option. - AddDeprecatedFlag(writer); - writer->WriteLine("public int $0$Count {", property_name()); - writer->WriteLine(" get { return $0$_.Count; }", name()); - writer->WriteLine("}"); - - AddDeprecatedFlag(writer); - writer->WriteLine("public $0$ Get$1$(int index) {", type_name(), - property_name()); - writer->WriteLine(" return $0$_[index];", name()); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public int $property_name$Count {\n" + " get { return $name$_.Count; }\n" + "}\n"); + + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public $type_name$ Get$property_name$(int index) {\n" + " return $name$_[index];\n" + "}\n"); } -void RepeatedMessageFieldGenerator::GenerateBuilderMembers(Writer* writer) { +void RepeatedMessageFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { // Note: We can return the original list here, because we make it unmodifiable when we build // We return it via IPopsicleList so that collection initializers work more pleasantly. - AddDeprecatedFlag(writer); - writer->WriteLine("public pbc::IPopsicleList<$0$> $1$List {", type_name(), - property_name()); - writer->WriteLine(" get { return PrepareBuilder().$0$_; }", name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public int $0$Count {", property_name()); - writer->WriteLine(" get { return result.$0$Count; }", property_name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public $0$ Get$1$(int index) {", type_name(), - property_name()); - writer->WriteLine(" return result.Get$0$(index);", property_name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Set$0$(int index, $1$ value) {", - property_name(), type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_[index] = value;", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public pbc::IPopsicleList<$type_name$> $property_name$List {\n" + " get { return PrepareBuilder().$name$_; }\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public int $property_name$Count {\n" + " get { return result.$property_name$Count; }\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public $type_name$ Get$property_name$(int index) {\n" + " return result.Get$property_name$(index);\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Set$property_name$(int index, $type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$name$_[index] = value;\n" + " return this;\n" + "}\n"); // Extra overload for builder (just on messages) - AddDeprecatedFlag(writer); - writer->WriteLine( - "public Builder Set$0$(int index, $1$.Builder builderForValue) {", - property_name(), type_name()); - AddNullCheck(writer, "builderForValue"); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_[index] = builderForValue.Build();", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Add$0$($1$ value) {", property_name(), - type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Add(value);", name(), type_name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Set$property_name$(int index, $type_name$.Builder builderForValue) {\n"); + AddNullCheck(printer, "builderForValue"); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$name$_[index] = builderForValue.Build();\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Add$property_name$($type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$name$_.Add(value);\n" + " return this;\n" + "}\n"); // Extra overload for builder (just on messages) - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Add$0$($1$.Builder builderForValue) {", - property_name(), type_name()); - AddNullCheck(writer, "builderForValue"); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Add(builderForValue.Build());", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine( - "public Builder AddRange$0$(scg::IEnumerable<$1$> values) {", - property_name(), type_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Add(values);", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Clear$0$() {", property_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Clear();", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Add$property_name$($type_name$.Builder builderForValue) {\n"); + AddNullCheck(printer, "builderForValue"); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$name$_.Add(builderForValue.Build());\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder AddRange$property_name$(scg::IEnumerable<$type_name$> values) {\n" + " PrepareBuilder();\n" + " result.$name$_.Add(values);\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Clear$property_name$() {\n" + " PrepareBuilder();\n" + " result.$name$_.Clear();\n" + " return this;\n" + "}\n"); } -void RepeatedMessageFieldGenerator::GenerateMergingCode(Writer* writer) { - writer->WriteLine("if (other.$0$_.Count != 0) {", name()); - writer->WriteLine(" result.$0$_.Add(other.$0$_);", name()); - writer->WriteLine("}"); +void RepeatedMessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { + printer->Print( + variables_, + "if (other.$name$_.Count != 0) {\n" + " result.$name$_.Add(other.$name$_);\n" + "}\n"); } -void RepeatedMessageFieldGenerator::GenerateBuildingCode(Writer* writer) { - writer->WriteLine("$0$_.MakeReadOnly();", name()); +void RepeatedMessageFieldGenerator::GenerateBuildingCode(io::Printer* printer) { + printer->Print(variables_, "$name$_.MakeReadOnly();\n"); } -void RepeatedMessageFieldGenerator::GenerateParsingCode(Writer* writer) { - writer->WriteLine( - "input.Read$0$Array(tag, field_name, result.$1$_, $2$.DefaultInstance, extensionRegistry);", - message_or_group(), name(), type_name()); +void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "input.Read$message_or_group$Array(tag, field_name, result.$name$_, $type_name$.DefaultInstance, extensionRegistry);\n"); } -void RepeatedMessageFieldGenerator::GenerateSerializationCode(Writer* writer) { - writer->WriteLine("if ($0$_.Count > 0) {", name()); - writer->Indent(); - writer->WriteLine("output.Write$0$Array($1$, field_names[$3$], $2$_);", - message_or_group(), number(), name(), field_ordinal()); - writer->Outdent(); - writer->WriteLine("}"); +void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($name$_.Count > 0) {\n" + " output.Write$message_or_group$Array($number$, field_names[$field_ordinal$], $name$_);\n" + "}\n"); } -void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { - writer->WriteLine("foreach ($0$ element in $1$List) {", type_name(), - property_name()); - writer->WriteLine( - " size += pb::CodedOutputStream.Compute$0$Size($1$, element);", - message_or_group(), number()); - writer->WriteLine("}"); +void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + printer->Print( + variables_, + "foreach ($type_name$ element in $property_name$List) {\n" + " size += pb::CodedOutputStream.Compute$message_or_group$Size($number$, element);\n" + "}\n"); } -void RepeatedMessageFieldGenerator::WriteHash(Writer* writer) { - writer->WriteLine("foreach($0$ i in $1$_)", type_name(), name()); - writer->WriteLine(" hash ^= i.GetHashCode();"); +void RepeatedMessageFieldGenerator::WriteHash(io::Printer* printer) { + printer->Print( + variables_, + "foreach($type_name$ i in $name$_)\n" + " hash ^= i.GetHashCode();\n"); } -void RepeatedMessageFieldGenerator::WriteEquals(Writer* writer) { - writer->WriteLine("if($0$_.Count != other.$0$_.Count) return false;", name()); - writer->WriteLine("for(int ix=0; ix < $0$_.Count; ix++)", name()); - writer->WriteLine(" if(!$0$_[ix].Equals(other.$0$_[ix])) return false;", - name()); +void RepeatedMessageFieldGenerator::WriteEquals(io::Printer* printer) { + printer->Print( + variables_, + "if($name$_.Count != other.$name$_.Count) return false;\n" + "for(int ix=0; ix < $name$_.Count; ix++)\n" + " if(!$name$_[ix].Equals(other.$name$_[ix])) return false;\n"); } -void RepeatedMessageFieldGenerator::WriteToString(Writer* writer) { - writer->WriteLine("PrintField(\"$0$\", $1$_, writer);", - GetFieldName(descriptor_), name()); +void RepeatedMessageFieldGenerator::WriteToString(io::Printer* printer) { + variables_["field_name"] = GetFieldName(descriptor_); + printer->Print( + variables_, + "PrintField(\"$field_name$\", $name$_, writer);\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h index 104274cb..9db76939 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h @@ -48,17 +48,17 @@ class RepeatedMessageFieldGenerator : public FieldGeneratorBase { RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~RepeatedMessageFieldGenerator(); - virtual void GenerateMembers(Writer* writer); - virtual void GenerateBuilderMembers(Writer* writer); - virtual void GenerateMergingCode(Writer* writer); - virtual void GenerateBuildingCode(Writer* writer); - virtual void GenerateParsingCode(Writer* writer); - virtual void GenerateSerializationCode(Writer* writer); - virtual void GenerateSerializedSizeCode(Writer* writer); + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateBuilderMembers(io::Printer* printer); + virtual void GenerateMergingCode(io::Printer* printer); + virtual void GenerateBuildingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); - virtual void WriteHash(Writer* writer); - virtual void WriteEquals(Writer* writer); - virtual void WriteToString(Writer* writer); + virtual void WriteHash(io::Printer* printer); + virtual void WriteEquals(io::Printer* printer); + virtual void WriteToString(io::Printer* printer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc index 8b285468..e27458bb 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc @@ -40,7 +40,6 @@ #include <google/protobuf/compiler/csharp/csharp_helpers.h> #include <google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h> -#include <google/protobuf/compiler/csharp/csharp_writer.h> namespace google { namespace protobuf { @@ -56,161 +55,182 @@ RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() { } -void RepeatedPrimitiveFieldGenerator::GenerateMembers(Writer* writer) { +void RepeatedPrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { if (descriptor_->is_packed() && optimize_speed()) { - writer->WriteLine("private int $0$MemoizedSerializedSize;", name()); + printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n"); } - writer->WriteLine( - "private pbc::PopsicleList<$0$> $1$_ = new pbc::PopsicleList<$0$>();", - type_name(), name()); - AddPublicMemberAttributes(writer); - writer->WriteLine("public scg::IList<$0$> $1$List {", type_name(), - property_name()); - writer->WriteLine(" get { return pbc::Lists.AsReadOnly($0$_); }", name()); - writer->WriteLine("}"); + printer->Print(variables_, + "private pbc::PopsicleList<$type_name$> $name$_ = new pbc::PopsicleList<$type_name$>();\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public scg::IList<$type_name$> $property_name$List {\n" + " get { return pbc::Lists.AsReadOnly($name$_); }\n" + "}\n"); // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option. - AddDeprecatedFlag(writer); - writer->WriteLine("public int $0$Count {", property_name()); - writer->WriteLine(" get { return $0$_.Count; }", name()); - writer->WriteLine("}"); - - AddPublicMemberAttributes(writer); - writer->WriteLine("public $0$ Get$1$(int index) {", type_name(), - property_name()); - writer->WriteLine(" return $0$_[index];", name()); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public int $property_name$Count {\n" + " get { return $name$_.Count; }\n" + "}\n"); + + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public $type_name$ Get$property_name$(int index) {\n" + " return $name$_[index];\n" + "}\n"); } -void RepeatedPrimitiveFieldGenerator::GenerateBuilderMembers(Writer* writer) { +void RepeatedPrimitiveFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { // Note: We can return the original list here, because we make it unmodifiable when we build // We return it via IPopsicleList so that collection initializers work more pleasantly. - AddPublicMemberAttributes(writer); - writer->WriteLine("public pbc::IPopsicleList<$0$> $1$List {", type_name(), - property_name()); - writer->WriteLine(" get { return PrepareBuilder().$0$_; }", name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public int $0$Count {", property_name()); - writer->WriteLine(" get { return result.$0$Count; }", property_name()); - writer->WriteLine("}"); - AddPublicMemberAttributes(writer); - writer->WriteLine("public $0$ Get$1$(int index) {", type_name(), - property_name()); - writer->WriteLine(" return result.Get$0$(index);", property_name()); - writer->WriteLine("}"); - AddPublicMemberAttributes(writer); - writer->WriteLine("public Builder Set$0$(int index, $1$ value) {", - property_name(), type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_[index] = value;", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddPublicMemberAttributes(writer); - writer->WriteLine("public Builder Add$0$($1$ value) {", property_name(), - type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Add(value);", name(), type_name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddPublicMemberAttributes(writer); - writer->WriteLine( - "public Builder AddRange$0$(scg::IEnumerable<$1$> values) {", - property_name(), type_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Add(values);", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Clear$0$() {", property_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Clear();", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public pbc::IPopsicleList<$type_name$> $property_name$List {\n" + " get { return PrepareBuilder().$name$_; }\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public int $property_name$Count {\n" + " get { return result.$property_name$Count; }\n" + "}\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public $type_name$ Get$property_name$(int index) {\n" + " return result.Get$property_name$(index);\n" + "}\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public Builder Set$property_name$(int index, $type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$name$_[index] = value;\n" + " return this;\n" + "}\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public Builder Add$property_name$($type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$name$_.Add(value);\n" + " return this;\n" + "}\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public Builder AddRange$property_name$(scg::IEnumerable<$type_name$> values) {\n" + " PrepareBuilder();\n" + " result.$name$_.Add(values);\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Clear$property_name$() {\n" + " PrepareBuilder();\n" + " result.$name$_.Clear();\n" + " return this;\n" + "}\n"); } -void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(Writer* writer) { - writer->WriteLine("if (other.$0$_.Count != 0) {", name()); - writer->WriteLine(" result.$0$_.Add(other.$0$_);", name()); - writer->WriteLine("}"); +void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { + printer->Print( + variables_, + "if (other.$name$_.Count != 0) {\n" + " result.$name$_.Add(other.$name$_);\n" + "}\n"); } -void RepeatedPrimitiveFieldGenerator::GenerateBuildingCode(Writer* writer) { - writer->WriteLine("$0$_.MakeReadOnly();", name()); +void RepeatedPrimitiveFieldGenerator::GenerateBuildingCode(io::Printer* printer) { + printer->Print(variables_, "$name$_.MakeReadOnly();\n"); } -void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(Writer* writer) { - writer->WriteLine("input.Read$0$Array(tag, field_name, result.$1$_);", - capitalized_type_name(), name()); +void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print(variables_, + "input.Read$capitalized_type_name$Array(tag, field_name, result.$name$_);\n"); } void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode( - Writer* writer) { - writer->WriteLine("if ($0$_.Count > 0) {", name()); - writer->Indent(); + io::Printer* printer) { + printer->Print(variables_, "if ($name$_.Count > 0) {\n"); + printer->Indent(); if (descriptor_->is_packed()) { - writer->WriteLine( - "output.WritePacked$0$Array($1$, field_names[$3$], $2$MemoizedSerializedSize, $2$_);", - capitalized_type_name(), number(), name(), field_ordinal()); + printer->Print(variables_, + "output.WritePacked$capitalized_type_name$Array($number$, field_names[$field_ordinal$], $name$MemoizedSerializedSize, $name$_);\n"); } else { - writer->WriteLine("output.Write$0$Array($1$, field_names[$3$], $2$_);", - capitalized_type_name(), number(), name(), - field_ordinal()); + printer->Print(variables_, + "output.Write$capitalized_type_name$Array($number$, field_names[$field_ordinal$], $name$_);\n"); } - writer->Outdent(); - writer->WriteLine("}"); + printer->Outdent(); + printer->Print("}\n"); } void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( - Writer* writer) { - writer->WriteLine("{"); - writer->Indent(); - writer->WriteLine("int dataSize = 0;"); + io::Printer* printer) { + printer->Print("{\n"); + printer->Indent(); + printer->Print("int dataSize = 0;\n"); int fixedSize = GetFixedSize(descriptor_->type()); if (fixedSize == -1) { - writer->WriteLine("foreach ($0$ element in $1$List) {", type_name(), - property_name()); - writer->WriteLine( - " dataSize += pb::CodedOutputStream.Compute$0$SizeNoTag(element);", - capitalized_type_name(), number()); - writer->WriteLine("}"); + printer->Print( + variables_, + "foreach ($type_name$ element in $property_name$List) {\n" + " dataSize += pb::CodedOutputStream.Compute$capitalized_type_name$SizeNoTag(element);\n" + "}\n"); } else { - writer->WriteLine("dataSize = $0$ * $1$_.Count;", SimpleItoa(fixedSize), name()); + printer->Print( + "dataSize = $size$ * $name$_.Count;\n", + "size", SimpleItoa(fixedSize), "name", name()); } - writer->WriteLine("size += dataSize;"); + printer->Print("size += dataSize;\n"); int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); if (descriptor_->is_packed()) { - writer->WriteLine("if ($0$_.Count != 0) {", name()); - writer->WriteLine( - " size += $0$ + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize);", - SimpleItoa(tagSize)); - writer->WriteLine("}"); + printer->Print( + "if ($name$_.Count != 0) {\n" + " size += $tag_size$ + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize);\n" + "}\n", + "name", name(), "tag_size", SimpleItoa(tagSize)); } else { - writer->WriteLine("size += $0$ * $1$_.Count;", SimpleItoa(tagSize), name()); + printer->Print( + "size += $tag_size$ * $name$_.Count;\n", + "tag_size", SimpleItoa(tagSize), "name", name()); } // cache the data size for packed fields. if (descriptor_->is_packed()) { - writer->WriteLine("$0$MemoizedSerializedSize = dataSize;", name()); + printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n"); } - writer->Outdent(); - writer->WriteLine("}"); + printer->Outdent(); + printer->Print("}\n"); } -void RepeatedPrimitiveFieldGenerator::WriteHash(Writer* writer) { - writer->WriteLine("foreach($0$ i in $1$_)", type_name(), name()); - writer->WriteLine(" hash ^= i.GetHashCode();"); +void RepeatedPrimitiveFieldGenerator::WriteHash(io::Printer* printer) { + printer->Print( + variables_, + "foreach($type_name$ i in $name$_)\n" + " hash ^= i.GetHashCode();\n"); } -void RepeatedPrimitiveFieldGenerator::WriteEquals(Writer* writer) { - writer->WriteLine("if($0$_.Count != other.$0$_.Count) return false;", name()); - writer->WriteLine("for(int ix=0; ix < $0$_.Count; ix++)", name()); - writer->WriteLine(" if(!$0$_[ix].Equals(other.$0$_[ix])) return false;", - name()); +void RepeatedPrimitiveFieldGenerator::WriteEquals(io::Printer* printer) { + printer->Print( + variables_, + "if($name$_.Count != other.$name$_.Count) return false;\n" + "for(int ix=0; ix < $name$_.Count; ix++)\n" + " if(!$name$_[ix].Equals(other.$name$_[ix])) return false;\n"); } -void RepeatedPrimitiveFieldGenerator::WriteToString(Writer* writer) { - writer->WriteLine("PrintField(\"$0$\", $1$_, writer);", descriptor_->name(), - name()); +void RepeatedPrimitiveFieldGenerator::WriteToString(io::Printer* printer) { + printer->Print(variables_, + "PrintField(\"$descriptor_name$\", $name$_, writer);\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h index 07b12015..50af9dda 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h @@ -48,17 +48,17 @@ class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase { RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~RepeatedPrimitiveFieldGenerator(); - virtual void GenerateMembers(Writer* writer); - virtual void GenerateBuilderMembers(Writer* writer); - virtual void GenerateMergingCode(Writer* writer); - virtual void GenerateBuildingCode(Writer* writer); - virtual void GenerateParsingCode(Writer* writer); - virtual void GenerateSerializationCode(Writer* writer); - virtual void GenerateSerializedSizeCode(Writer* writer); + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateBuilderMembers(io::Printer* printer); + virtual void GenerateMergingCode(io::Printer* printer); + virtual void GenerateBuildingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); - virtual void WriteHash(Writer* writer); - virtual void WriteEquals(Writer* writer); - virtual void WriteToString(Writer* writer); + virtual void WriteHash(io::Printer* printer); + virtual void WriteEquals(io::Printer* printer); + virtual void WriteToString(io::Printer* printer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator); diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc index 8dfb41d4..c52f6092 100644 --- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc @@ -39,7 +39,6 @@ #include <google/protobuf/compiler/csharp/csharp_source_generator_base.h> #include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_writer.h> namespace google { namespace protobuf { @@ -61,7 +60,7 @@ SourceGeneratorBase::SourceGeneratorBase(const FileDescriptor* descriptor) SourceGeneratorBase::~SourceGeneratorBase() { } -void SourceGeneratorBase::WriteGeneratedCodeAttributes(Writer* writer) { +void SourceGeneratorBase::WriteGeneratedCodeAttributes(io::Printer* printer) { // This hook can be used to reintroduce generated code attributes in the future. } diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h index 1955394e..61c19511 100644 --- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h @@ -40,8 +40,6 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class SourceGeneratorBase { protected: SourceGeneratorBase(const FileDescriptor* descriptor); @@ -62,7 +60,7 @@ class SourceGeneratorBase { return runtimeSuffix_; } - void WriteGeneratedCodeAttributes(Writer* writer); + void WriteGeneratedCodeAttributes(io::Printer* printer); private: const FileDescriptor* descriptor_; diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc index 358cfa4f..b14bf5e8 100644 --- a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc +++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc @@ -42,7 +42,6 @@ #include <google/protobuf/compiler/csharp/csharp_extension.h> #include <google/protobuf/compiler/csharp/csharp_helpers.h> #include <google/protobuf/compiler/csharp/csharp_message.h> -#include <google/protobuf/compiler/csharp/csharp_writer.h> namespace google { namespace protobuf { @@ -60,218 +59,224 @@ UmbrellaClassGenerator::UmbrellaClassGenerator(const FileDescriptor* file) UmbrellaClassGenerator::~UmbrellaClassGenerator() { } -void UmbrellaClassGenerator::Generate(Writer* writer) { - WriteIntroduction(writer); - WriteExtensionRegistration(writer); +void UmbrellaClassGenerator::Generate(io::Printer* printer) { + WriteIntroduction(printer); + WriteExtensionRegistration(printer); // write children: Extensions if (file_->extension_count() > 0) { - writer->WriteLine("#region Extensions"); + printer->Print("#region Extensions\n"); for (int i = 0; i < file_->extension_count(); i++) { ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.Generate(writer); + extensionGenerator.Generate(printer); } - writer->WriteLine("#endregion"); - writer->WriteLine(); + printer->Print("#endregion\n"); + printer->Print("\n"); } - writer->WriteLine("#region Static variables"); + printer->Print("#region Static variables\n"); for (int i = 0; i < file_->message_type_count(); i++) { MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.GenerateStaticVariables(writer); + messageGenerator.GenerateStaticVariables(printer); } - writer->WriteLine("#endregion"); + printer->Print("#endregion\n"); if (!use_lite_runtime()) { - WriteDescriptor(writer); + WriteDescriptor(printer); } else { - WriteLiteExtensions(writer); + WriteLiteExtensions(printer); } // Close the class declaration. - writer->Outdent(); - writer->WriteLine("}"); + printer->Outdent(); + printer->Print("}\n"); // Close the namespace around the umbrella class if defined if (!umbrellaNamespace_.empty()) { - writer->Outdent(); - writer->WriteLine("}"); + printer->Outdent(); + printer->Print("}\n"); } // write children: Enums if (file_->enum_type_count() > 0) { - writer->WriteLine("#region Enums"); + printer->Print("#region Enums\n"); for (int i = 0; i < file_->enum_type_count(); i++) { EnumGenerator enumGenerator(file_->enum_type(i)); - enumGenerator.Generate(writer); + enumGenerator.Generate(printer); } - writer->WriteLine("#endregion"); - writer->WriteLine(); + printer->Print("#endregion\n"); + printer->Print("\n"); } // write children: Messages if (file_->message_type_count() > 0) { - writer->WriteLine("#region Messages"); + printer->Print("#region Messages\n"); for (int i = 0; i < file_->message_type_count(); i++) { MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.Generate(writer); + messageGenerator.Generate(printer); } - writer->WriteLine("#endregion"); - writer->WriteLine(); + printer->Print("#endregion\n"); + printer->Print("\n"); } // TODO(jtattermusch): add insertion point for services. if (!namespace_.empty()) { - writer->Outdent(); - writer->WriteLine("}"); + printer->Outdent(); + printer->Print("}\n"); } - writer->WriteLine(); - writer->WriteLine("#endregion Designer generated code"); + printer->Print("\n"); + printer->Print("#endregion Designer generated code\n"); } -void UmbrellaClassGenerator::WriteIntroduction(Writer* writer) { - writer->WriteLine( - "// Generated by the protocol buffer compiler. DO NOT EDIT!"); - writer->WriteLine("// source: $0$", file_->name()); - writer->WriteLine("#pragma warning disable 1591, 0612, 3021"); - writer->WriteLine("#region Designer generated code"); - - writer->WriteLine(); - writer->WriteLine("using pb = global::Google.ProtocolBuffers;"); - writer->WriteLine("using pbc = global::Google.ProtocolBuffers.Collections;"); - writer->WriteLine("using pbd = global::Google.ProtocolBuffers.Descriptors;"); - writer->WriteLine("using scg = global::System.Collections.Generic;"); +void UmbrellaClassGenerator::WriteIntroduction(io::Printer* printer) { + printer->Print( + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// source: $file_name$\n" + "#pragma warning disable 1591, 0612, 3021\n" + "#region Designer generated code\n" + "\n" + "using pb = global::Google.ProtocolBuffers;\n" + "using pbc = global::Google.ProtocolBuffers.Collections;\n" + "using pbd = global::Google.ProtocolBuffers.Descriptors;\n" + "using scg = global::System.Collections.Generic;\n", + "file_name", file_->name()); if (!namespace_.empty()) { - writer->WriteLine("namespace $0$ {", namespace_); - writer->Indent(); - writer->WriteLine(); + printer->Print("namespace $namespace$ {\n", "namespace", namespace_); + printer->Indent(); + printer->Print("\n"); } // Add the namespace around the umbrella class if defined if (!umbrellaNamespace_.empty()) { - writer->WriteLine("namespace $0$ {", umbrellaNamespace_); - writer->Indent(); - writer->WriteLine(); + printer->Print("namespace $umbrella_namespace$ {\n", + "umbrella_namespace", umbrellaNamespace_); + printer->Indent(); + printer->Print("\n"); } - writer->WriteLine( - "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); - WriteGeneratedCodeAttributes(writer); - writer->WriteLine("$0$ static partial class $1$ {", class_access_level(), - umbrellaClassname_); - writer->WriteLine(); - writer->Indent(); + printer->Print( + "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); + WriteGeneratedCodeAttributes(printer); + printer->Print( + "$access_level$ static partial class $umbrella_class_name$ {\n" + "\n", + "access_level", class_access_level(), + "umbrella_class_name", umbrellaClassname_); + printer->Indent(); } -void UmbrellaClassGenerator::WriteExtensionRegistration(Writer* writer) { - writer->WriteLine("#region Extension registration"); - writer->WriteLine( - "public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {"); - writer->Indent(); +void UmbrellaClassGenerator::WriteExtensionRegistration(io::Printer* printer) { + printer->Print( + "#region Extension registration\n" + "public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {\n"); + printer->Indent(); for (int i = 0; i < file_->extension_count(); i++) { ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.GenerateExtensionRegistrationCode(writer); + extensionGenerator.GenerateExtensionRegistrationCode(printer); } for (int i = 0; i < file_->message_type_count(); i++) { MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.GenerateExtensionRegistrationCode(writer); + messageGenerator.GenerateExtensionRegistrationCode(printer); } - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine("#endregion"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("#endregion\n"); } -void UmbrellaClassGenerator::WriteDescriptor(Writer* writer) { - writer->WriteLine("#region Descriptor"); - - writer->WriteLine("public static pbd::FileDescriptor Descriptor {"); - writer->WriteLine(" get { return descriptor; }"); - writer->WriteLine("}"); - writer->WriteLine("private static pbd::FileDescriptor descriptor;"); - writer->WriteLine(); - writer->WriteLine("static $0$() {", umbrellaClassname_); - writer->Indent(); - writer->WriteLine( - "byte[] descriptorData = global::System.Convert.FromBase64String("); - writer->Indent(); - writer->Indent(); - writer->WriteLine("string.Concat("); - writer->Indent(); +void UmbrellaClassGenerator::WriteDescriptor(io::Printer* printer) { + printer->Print( + "#region Descriptor\n" + "public static pbd::FileDescriptor Descriptor {\n" + " get { return descriptor; }\n" + "}\n" + "private static pbd::FileDescriptor descriptor;\n" + "\n" + "static $umbrella_class_name$() {\n", + "umbrella_class_name", umbrellaClassname_); + printer->Indent(); + printer->Print( + "byte[] descriptorData = global::System.Convert.FromBase64String(\n"); + printer->Indent(); + printer->Indent(); + printer->Print("string.Concat(\n"); + printer->Indent(); // TODO(jonskeet): Consider a C#-escaping format here instead of just Base64. std::string base64 = FileDescriptorToBase64(file_); while (base64.size() > 60) { - writer->WriteLine("\"$0$\", ", base64.substr(0, 60)); + printer->Print("\"$base64$\", \n", "base64", base64.substr(0, 60)); base64 = base64.substr(60); } - writer->Outdent(); - writer->WriteLine("\"$0$\"));", base64); - writer->Outdent(); - writer->Outdent(); - writer->WriteLine( - "pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {"); - writer->Indent(); - writer->WriteLine("descriptor = root;"); + printer->Outdent(); + printer->Print("\"$base64$\"));\n", "base64", base64); + printer->Outdent(); + printer->Outdent(); + printer->Print( + "pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {\n"); + printer->Indent(); + printer->Print("descriptor = root;\n"); for (int i = 0; i < file_->message_type_count(); i++) { MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.GenerateStaticVariableInitializers(writer); + messageGenerator.GenerateStaticVariableInitializers(printer); } for (int i = 0; i < file_->extension_count(); i++) { ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.GenerateStaticVariableInitializers(writer); + extensionGenerator.GenerateStaticVariableInitializers(printer); } if (uses_extensions()) { // Must construct an ExtensionRegistry containing all possible extensions // and return it. - writer->WriteLine( - "pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();"); - writer->WriteLine("RegisterAllExtensions(registry);"); + printer->Print( + "pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();\n"); + printer->Print("RegisterAllExtensions(registry);\n"); for (int i = 0; i < file_->dependency_count(); i++) { - writer->WriteLine("$0$.RegisterAllExtensions(registry);", - GetFullUmbrellaClassName(file_->dependency(i))); + printer->Print("$dependency$.RegisterAllExtensions(registry);\n", + "dependency", GetFullUmbrellaClassName(file_->dependency(i))); } - writer->WriteLine("return registry;"); + printer->Print("return registry;\n"); } else { - writer->WriteLine("return null;"); + printer->Print("return null;\n"); } - writer->Outdent(); - writer->WriteLine("};"); + printer->Outdent(); + printer->Print("};\n"); // ----------------------------------------------------------------- // Invoke internalBuildGeneratedFileFrom() to build the file. - writer->WriteLine( - "pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,"); - writer->WriteLine(" new pbd::FileDescriptor[] {"); + printer->Print( + "pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,\n"); + printer->Print(" new pbd::FileDescriptor[] {\n"); for (int i = 0; i < file_->dependency_count(); i++) { - writer->WriteLine(" $0$.Descriptor, ", - GetFullUmbrellaClassName(file_->dependency(i))); + printer->Print( + " $full_umbrella_class_name$.Descriptor, \n", + "full_umbrella_class_name", + GetFullUmbrellaClassName(file_->dependency(i))); } - writer->WriteLine(" }, assigner);"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine("#endregion"); - writer->WriteLine(); + printer->Print(" }, assigner);\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("#endregion\n\n"); } -void UmbrellaClassGenerator::WriteLiteExtensions(Writer* writer) { - writer->WriteLine("#region Extensions"); - writer->WriteLine("internal static readonly object Descriptor;"); - writer->WriteLine("static $0$() {", umbrellaClassname_); - writer->Indent(); - writer->WriteLine("Descriptor = null;"); +void UmbrellaClassGenerator::WriteLiteExtensions(io::Printer* printer) { + printer->Print( + "#region Extensions\n" + "internal static readonly object Descriptor;\n" + "static $umbrella_class_name$() {\n", + "umbrella_class_name", umbrellaClassname_); + printer->Indent(); + printer->Print("Descriptor = null;\n"); for (int i = 0; i < file_->message_type_count(); i++) { MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.GenerateStaticVariableInitializers(writer); + messageGenerator.GenerateStaticVariableInitializers(printer); } for (int i = 0; i < file_->extension_count(); i++) { ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.GenerateStaticVariableInitializers(writer); + extensionGenerator.GenerateStaticVariableInitializers(printer); } - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine("#endregion"); - writer->WriteLine(); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("#endregion\n\n"); } bool UmbrellaClassGenerator::uses_extensions() { diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h index 757f8f91..83e1f347 100644 --- a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h +++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h @@ -48,7 +48,7 @@ class UmbrellaClassGenerator : public SourceGeneratorBase { UmbrellaClassGenerator(const FileDescriptor* file); ~UmbrellaClassGenerator(); - void Generate(Writer* write); + void Generate(io::Printer* printer); private: const FileDescriptor* file_; @@ -57,10 +57,10 @@ class UmbrellaClassGenerator : public SourceGeneratorBase { std::string umbrellaClassname_; std::string umbrellaNamespace_; - void WriteIntroduction(Writer* writer); - void WriteExtensionRegistration(Writer* writer); - void WriteDescriptor(Writer* writer); - void WriteLiteExtensions(Writer* write); + void WriteIntroduction(io::Printer* printer); + void WriteExtensionRegistration(io::Printer* printer); + void WriteDescriptor(io::Printer* printer); + void WriteLiteExtensions(io::Printer* printer); bool uses_extensions(); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc index d6609692..30a13ddb 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc @@ -55,8 +55,6 @@ void SetEnumVariables(const FieldDescriptor* descriptor, (descriptor->file() != descriptor->enum_type()->file())) { (*variables)["property_type"] = "enum " + 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"; @@ -74,11 +72,9 @@ 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"); + " .dataTypeSpecific.enumDescFunc = $enum_desc_func$,\n"); } void EnumFieldGenerator::GenerateCFunctionDeclarations( @@ -103,7 +99,7 @@ void EnumFieldGenerator::GenerateCFunctionImplementations( "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" + " return GPBGetMessageInt32Field(message, field);\n" "}\n" "\n" "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value) {\n" @@ -137,11 +133,9 @@ 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"); + " .dataTypeSpecific.enumDescFunc = $enum_desc_func$,\n"); } } // namespace objectivec diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc index 76137c80..4e348393 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc @@ -46,24 +46,6 @@ ExtensionGenerator::ExtensionGenerator(const string& root_class_name, : 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 cases, so it seems to be ok to use as a back door for errors. @@ -77,10 +59,6 @@ ExtensionGenerator::ExtensionGenerator(const string& root_class_name, ExtensionGenerator::~ExtensionGenerator() {} void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) { - if (IsFiltered()) { - printer->Print("// $filter_reason$\n\n", "filter_reason", filter_reason_); - return; - } map<string, string> vars; vars["method_name"] = method_name_; SourceLocation location; @@ -91,15 +69,11 @@ void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) { } printer->Print(vars, "$comments$" - "+ (GPBExtensionField*)$method_name$;\n"); + "+ (GPBExtensionDescriptor *)$method_name$;\n"); } void ExtensionGenerator::GenerateStaticVariablesInitialization( - io::Printer* printer, bool* out_generated, bool root) { - if (IsFiltered()) { - return; - } - *out_generated = true; + io::Printer* printer) { map<string, string> vars; vars["root_class_and_method_name"] = root_class_and_method_name_; vars["extended_type"] = ClassName(descriptor_->containing_type()); @@ -122,14 +96,14 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( vars["type"] = "NULL"; } - vars["default_name"] = GPBValueFieldName(descriptor_); + vars["default_name"] = GPBGenericValueFieldName(descriptor_); if (descriptor_->is_repeated()) { vars["default"] = "nil"; } else { vars["default"] = DefaultValue(descriptor_); } string type = GetCapitalizedType(descriptor_); - vars["extension_type"] = string("GPBType") + type; + vars["extension_type"] = string("GPBDataType") + type; if (objc_type == OBJECTIVECTYPE_ENUM) { vars["enum_desc_func_name"] = @@ -141,7 +115,7 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( printer->Print(vars, "{\n" " .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n" - " .type = $extension_type$,\n" + " .dataType = $extension_type$,\n" " .extendedClass = GPBStringifySymbol($extended_type$),\n" " .fieldNumber = $number$,\n" " .defaultValue.$default_name$ = $default$,\n" @@ -152,9 +126,6 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( } 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_); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.h b/src/google/protobuf/compiler/objectivec/objectivec_extension.h index 553f0887..e361e639 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_extension.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.h @@ -52,16 +52,12 @@ class ExtensionGenerator { ~ExtensionGenerator(); void GenerateMembersHeader(io::Printer* printer); - void GenerateStaticVariablesInitialization(io::Printer* printer, - bool* out_generated, bool root); + void GenerateStaticVariablesInitialization(io::Printer* printer); 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); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc index c5f05653..cf5d8cfb 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc @@ -87,18 +87,16 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, 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)["default_name"] = GPBGenericValueFieldName(descriptor); - (*variables)["typeSpecific_name"] = "className"; - (*variables)["typeSpecific_value"] = "NULL"; + (*variables)["dataTypeSpecific_name"] = "className"; + (*variables)["dataTypeSpecific_value"] = "NULL"; string field_options = descriptor->options().SerializeAsString(); // Must convert to a standard byte order for packing length into @@ -117,45 +115,6 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, (*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) { @@ -163,12 +122,7 @@ FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) { 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()) { + if (field->is_map()) { result = new MapFieldGenerator(field); } else { result = new RepeatedMessageFieldGenerator(field); @@ -185,14 +139,7 @@ FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) { } 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); - } + result = new MessageFieldGenerator(field); break; } case OBJECTIVECTYPE_ENUM: @@ -249,11 +196,17 @@ void FieldGenerator::GenerateFieldDescription( " .number = $field_number_name$,\n" " .hasIndex = $has_index$,\n" " .flags = $fieldflags$,\n" - " .type = GPBType$field_type$,\n" - " .offset = offsetof($classname$_Storage, $name$),\n" + " .dataType = GPBDataType$field_type$,\n" + " .offset = offsetof($classname$__storage_, $name$),\n" " .defaultValue.$default_name$ = $default$,\n"); - // " .typeSpecific.value* = [something]," + // TODO(thomasvl): It might be useful to add a CPP wrapper to support + // compiling away the EnumDescriptors. To do that, we'd need a #if here + // to control setting the descriptor vs. the validator, and above in + // SetCommonFieldVariables() we'd want to wrap how we add + // GPBFieldHasDefaultValue to the flags. + + // " .dataTypeSpecific.value* = [something]," GenerateFieldDescriptionTypeSpecific(printer); const string& field_options(variables_.find("fieldoptions")->second); @@ -280,7 +233,7 @@ void FieldGenerator::GenerateFieldDescriptionTypeSpecific( io::Printer* printer) const { printer->Print( variables_, - " .typeSpecific.$typeSpecific_name$ = $typeSpecific_value$,\n"); + " .dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n"); } void FieldGenerator::SetOneofIndexBase(int index_base) { @@ -378,7 +331,7 @@ void ObjCObjFieldGenerator::GeneratePropertyDeclaration( } printer->Print( variables_, - "@property(nonatomic, readwrite, $property_storage_attribute$) $property_type$ *$name$$storage_attribute$;\n"); + "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$;\n"); if (IsInitName(variables_.find("name")->second)) { // 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 @@ -410,22 +363,24 @@ void RepeatedFieldGenerator::GenerateFieldStorageDeclaration( void RepeatedFieldGenerator::GeneratePropertyImplementation( io::Printer* printer) const { - printer->Print(variables_, "@dynamic $name$;\n"); + printer->Print(variables_, "@dynamic $name$, $name$_Count;\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.) + // Repeated fields don't need the has* properties, but they do expose a + // *Count (to check without autocreation). So for the field property we need + // 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"); + "@property(nonatomic, readwrite, strong, null_resettable) $array_storage_type$ *$name$$storage_attribute$;\n" + "@property(nonatomic, readonly) NSUInteger $name$_Count;\n"); if (IsInitName(variables_.find("name")->second)) { // 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 diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc index d04eee85..5a5c9e9b 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc @@ -54,35 +54,24 @@ namespace objectivec { FileGenerator::FileGenerator(const FileDescriptor *file) : file_(file), root_class_name_(FileClassName(file)), - is_filtered_(true), - all_extensions_filtered_(true), is_public_dep_(false) { - // Validate the objc prefix, do this even if the file's contents are filtered - // to catch a bad prefix as soon as it is found. + // Validate the objc prefix. ValidateObjCClassPrefix(file_); 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() { @@ -116,8 +105,7 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { "protoc_gen_objc_version", SimpleItoa(GOOGLE_PROTOBUF_OBJC_GEN_VERSION)); - const vector<FileGenerator *> &dependency_generators = - DependencyGenerators(); + const vector<FileGenerator *> &dependency_generators = DependencyGenerators(); for (vector<FileGenerator *>::const_iterator iter = dependency_generators.begin(); iter != dependency_generators.end(); ++iter) { @@ -129,25 +117,27 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { printer->Print( "// @@protoc_insertion_point(imports)\n" + "\n" + "CF_EXTERN_C_BEGIN\n" "\n"); - printer->Print("CF_EXTERN_C_BEGIN\n\n"); - - if (!IsFiltered()) { - set<string> fwd_decls; - for (vector<MessageGenerator *>::iterator iter = message_generators_.begin(); - iter != message_generators_.end(); ++iter) { - (*iter)->DetermineForwardDeclarations(&fwd_decls); - } - for (set<string>::const_iterator i(fwd_decls.begin()); - i != fwd_decls.end(); ++i) { - printer->Print("$value$;\n", "value", *i); - } - if (fwd_decls.begin() != fwd_decls.end()) { - printer->Print("\n"); - } + set<string> fwd_decls; + for (vector<MessageGenerator *>::iterator iter = message_generators_.begin(); + iter != message_generators_.end(); ++iter) { + (*iter)->DetermineForwardDeclarations(&fwd_decls); + } + for (set<string>::const_iterator i(fwd_decls.begin()); + i != fwd_decls.end(); ++i) { + printer->Print("$value$;\n", "value", *i); + } + if (fwd_decls.begin() != fwd_decls.end()) { + printer->Print("\n"); } + printer->Print( + "NS_ASSUME_NONNULL_BEGIN\n" + "\n"); + // need to write out all enums first for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin(); iter != enum_generators_.end(); ++iter) { @@ -160,36 +150,26 @@ void FileGenerator::GenerateHeader(io::Printer *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" - "\n" - "// The base class provides:\n" - "// + (GPBExtensionRegistry *)extensionRegistry;\n" - "// which is an GPBExtensionRegistry that includes all the extensions defined by\n" - "// this file and all files that it depends on.\n" - "\n" - "@end\n" - "\n", - "root_class_name", root_class_name_); - } + // are no extensions. + printer->Print( + "#pragma mark - $root_class_name$\n" + "\n" + "@interface $root_class_name$ : GPBRootObject\n" + "\n" + "// The base class provides:\n" + "// + (GPBExtensionRegistry *)extensionRegistry;\n" + "// which is an GPBExtensionRegistry that includes all the extensions defined by\n" + "// this file and all files that it depends on.\n" + "\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 = "// "; - } + // The dynamic methods block is only needed if there are extensions. printer->Print( - "$root_line_prefix$@interface $root_class_name$ (DynamicMethods)\n", - "root_class_name", root_class_name_, - "root_line_prefix", root_line_prefix); + "@interface $root_class_name$ (DynamicMethods)\n", + "root_class_name", root_class_name_); for (vector<ExtensionGenerator *>::iterator iter = extension_generators_.begin(); @@ -197,8 +177,7 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { (*iter)->GenerateMembersHeader(printer); } - printer->Print("$root_line_prefix$@end\n\n", - "root_line_prefix", root_line_prefix); + printer->Print("@end\n\n"); } // extension_generators_.size() > 0 for (vector<MessageGenerator *>::iterator iter = message_generators_.begin(); @@ -206,11 +185,12 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { (*iter)->GenerateMessageHeader(printer); } - printer->Print("CF_EXTERN_C_END\n"); - printer->Print( - "\n" - "// @@protoc_insertion_point(global_scope)\n"); + "NS_ASSUME_NONNULL_END\n" + "\n" + "CF_EXTERN_C_END\n" + "\n" + "// @@protoc_insertion_point(global_scope)\n"); } void FileGenerator::GenerateSource(io::Printer *printer) { @@ -239,136 +219,119 @@ void FileGenerator::GenerateSource(io::Printer *printer) { "// @@protoc_insertion_point(imports)\n" "\n"); - 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" - "\n" - "// @@protoc_insertion_point(global_scope)\n", - "root_class_name", root_class_name_); - return; - } - printer->Print( "#pragma mark - $root_class_name$\n" "\n" "@implementation $root_class_name$\n\n", "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"); - } + // Generate the extension initialization structures for the top level and + // any nested messages. + ostringstream extensions_stringstream; + if (file_->extension_count() + file_->message_type_count() > 0) { + io::OstreamOutputStream extensions_outputstream(&extensions_stringstream); + io::Printer extensions_printer(&extensions_outputstream, '$'); + for (vector<ExtensionGenerator *>::iterator iter = + extension_generators_.begin(); + iter != extension_generators_.end(); ++iter) { + (*iter)->GenerateStaticVariablesInitialization(&extensions_printer); } + for (vector<MessageGenerator *>::iterator iter = + message_generators_.begin(); + iter != message_generators_.end(); ++iter) { + (*iter)->GenerateStaticVariablesInitialization(&extensions_printer); + } + extensions_stringstream.flush(); + } - if (generated_extensions) { + // If there were any extensions or this file has any dependencies, output + // a registry to override to create the file specific registry. + const string& extensions_str = extensions_stringstream.str(); + if (extensions_str.length() > 0 || file_->dependency_count() > 0) { + 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" + " GPBDebugCheckRuntimeVersion();\n" + " registry = [[GPBExtensionRegistry alloc] init];\n"); + + printer->Indent(); + printer->Indent(); + + if (extensions_str.length() > 0) { 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(); + "static GPBExtensionDescription descriptions[] = {\n"); printer->Indent(); - - extensions_stringstream.flush(); - printer->Print(extensions_stringstream.str().c_str()); - printer->Outdent(); + printer->Print(extensions_str.c_str()); printer->Outdent(); + printer->Print( + "};\n" + "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n" + " GPBExtensionDescriptor *extension =\n" + " [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]];\n" + " [registry addExtension:extension];\n" + " [self globallyRegisterExtension:extension];\n" + " [extension release];\n" + "}\n"); + } + const vector<FileGenerator *> &dependency_generators = + DependencyGenerators(); + for (vector<FileGenerator *>::const_iterator iter = + dependency_generators.begin(); + iter != dependency_generators.end(); ++iter) { printer->Print( - " }\n" - " return registry;\n" - "}\n" - "\n"); + "[registry addExtensions:[$dependency$ extensionRegistry]];\n", + "dependency", (*iter)->RootClassName()); } + + printer->Outdent(); + printer->Outdent(); + + printer->Print( + " }\n" + " return registry;\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; + // File descriptor only needed if there are messages to use it. + if (message_generators_.size() > 0) { + 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( + "#pragma mark - $root_class_name$_FileDescriptor\n" + "\n" + "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" + " GPBDebugCheckRuntimeVersion();\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); } - 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) { diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h index 95d17bfd..1bb4f0ea 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.h @@ -64,8 +64,6 @@ class FileGenerator { 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_; } bool IsPublicDependency() const { return is_public_dep_; } protected: @@ -84,8 +82,6 @@ class FileGenerator { vector<EnumGenerator*> enum_generators_; vector<MessageGenerator*> message_generators_; vector<ExtensionGenerator*> extension_generators_; - bool is_filtered_; - bool all_extensions_filtered_; bool is_public_dep_; const vector<FileGenerator*>& DependencyGenerators(); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc index 17776715..85e438f4 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc @@ -58,10 +58,6 @@ bool ObjectiveCGenerator::Generate(const FileDescriptor* file, return false; } - if (!InitializeClassWhitelist(error)) { - return false; - } - FileGenerator file_generator(file); string filepath = FilePath(file); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc index 6d6e5959..9b645f09 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc @@ -50,8 +50,6 @@ namespace objectivec { namespace { -hash_set<string> gClassWhitelist; - // islower()/isupper()/tolower()/toupper() change based on locale. // // src/google/protobuf/stubs/strutil.h:150 has the same pattern. For the @@ -580,7 +578,7 @@ string GetCapitalizedType(const FieldDescriptor* field) { case FieldDescriptor::TYPE_STRING: return "String"; case FieldDescriptor::TYPE_BYTES: - return "Data"; + return "Bytes"; case FieldDescriptor::TYPE_ENUM: return "Enum"; case FieldDescriptor::TYPE_GROUP: @@ -684,8 +682,9 @@ static string HandleExtremeFloatingPoint(string val, bool add_float_suffix) { } } -string GPBValueFieldName(const FieldDescriptor* field) { - // Returns the field within the GPBValue union to use for the given field. +string GPBGenericValueFieldName(const FieldDescriptor* field) { + // Returns the field within the GPBGenericValue union to use for the given + // field. if (field->is_repeated()) { return "valueMessage"; } @@ -831,60 +830,6 @@ string BuildCommentsString(const SourceLocation& location) { return final_comments; } -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 key, const string& input_for_decode, const string& desired_output) { diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h index 19317698..10d51a34 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h @@ -138,16 +138,13 @@ inline ObjectiveCType GetObjectiveCType(const FieldDescriptor* field) { bool IsPrimitiveType(const FieldDescriptor* field); bool IsReferenceType(const FieldDescriptor* field); -string GPBValueFieldName(const FieldDescriptor* field); +string GPBGenericValueFieldName(const FieldDescriptor* field); string DefaultValue(const FieldDescriptor* field); string BuildFlagsString(const vector<string>& strings); string BuildCommentsString(const SourceLocation& location); -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 LIBPROTOC_EXPORT TextFormatDecodeData { diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc index b091b77a..dc1cef55 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc @@ -242,6 +242,14 @@ TEST(ObjCHelperDeathTest, TextFormatDecodeData_Failures) { } #endif // PROTOBUF_HAS_DEATH_TEST +// TODO(thomasvl): Should probably add some unittests for all the special cases +// of name mangling (class name, field name, enum names). Rather than doing +// this with an ObjC test in the objectivec directory, we should be able to +// use src/google/protobuf/compiler/importer* (like other tests) to support a +// virtual file system to feed in protos, once we have the Descriptor tree, the +// tests could use the helper methods for generating names and validate the +// right things are happening. + } // namespace } // namespace objectivec } // namespace compiler diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc index 52e583bf..32671d42 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc @@ -178,49 +178,25 @@ MessageGenerator::MessageGenerator(const string& root_classname, : 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."; + class_name_(ClassName(descriptor_)) { + for (int i = 0; i < descriptor_->extension_count(); i++) { + extension_generators_.push_back( + new ExtensionGenerator(class_name_, descriptor_->extension(i))); } - 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 generate 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); - } + + 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(); + new MessageGenerator(root_classname_, descriptor_->nested_type(i)); nested_message_generators_.push_back(generator); } } @@ -236,31 +212,26 @@ MessageGenerator::~MessageGenerator() { } 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); - } + io::Printer* printer) { + for (vector<ExtensionGenerator*>::iterator iter = + extension_generators_.begin(); + iter != extension_generators_.end(); ++iter) { + (*iter)->GenerateStaticVariablesInitialization(printer); } - // 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); + (*iter)->GenerateStaticVariablesInitialization(printer); } } void MessageGenerator::DetermineForwardDeclarations(set<string>* fwd_decls) { - if (!IsFiltered() && !IsMapEntryMessage(descriptor_)) { + if (!IsMapEntryMessage(descriptor_)) { for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* fieldDescriptor = descriptor_->field(i); - // If it is a the field is repeated, the type will be and *Array, - // and we don't need any forward decl. + // If it is a the field is repeated, the type will be and *Array, and we + // don't need any forward decl. if (fieldDescriptor->is_repeated()) { continue; } @@ -291,12 +262,10 @@ void MessageGenerator::GenerateEnumHeader(io::Printer* 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<ExtensionGenerator*>::iterator iter = + extension_generators_.begin(); + iter != extension_generators_.end(); ++iter) { + (*iter)->GenerateRegistrationSource(printer); } for (vector<MessageGenerator*>::iterator iter = @@ -317,101 +286,84 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { return; } - if (IsFiltered()) { - printer->Print("// $filter_reason$\n\n", - "filter_reason", filter_reason_); - } else { - printer->Print( - "#pragma mark - $classname$\n" - "\n", - "classname", class_name_); + 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"); - } - } + if (descriptor_->field_count()) { + scoped_array<const FieldDescriptor*> sorted_fields( + SortFieldsByNumber(descriptor_)); - for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin(); - iter != oneof_generators_.end(); ++iter) { - (*iter)->GenerateCaseEnum(printer); - } + printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n", + "classname", class_name_); + printer->Indent(); - string message_comments; - SourceLocation location; - if (descriptor_->GetSourceLocation(&location)) { - message_comments = BuildCommentsString(location); - } else { - message_comments = ""; + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(sorted_fields[i]) + .GenerateFieldNumberConstant(printer); } - printer->Print( - "$comments$@interface $classname$ : GPBMessage\n\n", - "classname", class_name_, - "comments", message_comments); + printer->Outdent(); + printer->Print("};\n\n"); + } - vector<char> seen_oneofs(descriptor_->oneof_decl_count(), 0); - 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] = 1; - oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration( - printer); - } + 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<char> seen_oneofs(descriptor_->oneof_decl_count(), 0); + 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] = 1; + oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration( + printer); } - field_generators_.get(field) - .GeneratePropertyDeclaration(printer); } + field_generators_.get(field).GeneratePropertyDeclaration(printer); + } - printer->Print("@end\n\n"); + printer->Print("@end\n\n"); - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateCFunctionDeclarations(printer); - } + 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 (!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"); + 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 = @@ -422,7 +374,7 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { } void MessageGenerator::GenerateSource(io::Printer* printer) { - if (!IsFiltered() && !IsMapEntryMessage(descriptor_)) { + if (!IsMapEntryMessage(descriptor_)) { printer->Print( "#pragma mark - $classname$\n" "\n", @@ -454,6 +406,23 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { sort(sorted_extensions.begin(), sorted_extensions.end(), ExtensionRangeOrdering()); + // TODO(thomasvl): Finish optimizing has bit. The current behavior is as + // follows: + // 1. objectivec_field.cc's SetCommonFieldVariables() defaults the has_index + // to the field's index in the list of fields. + // 2. RepeatedFieldGenerator::RepeatedFieldGenerator() sets has_index to + // GPBNoHasBit because repeated fields & map<> fields don't use the has + // bit. + // 3. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative + // index that groups all the elements on of the oneof. + // So in has_storage, we need enough bits for the single fields that aren't + // in any oneof, and then one int32 for each oneof (to store the field + // number). So we could save a little space by not using the field's index + // and instead make a second pass only assigning indexes for the fields + // that would need it. The only savings would come when messages have over + // a multiple of 32 fields with some number being repeated or in oneofs to + // drop the count below that 32 multiple; so it hasn't seemed worth doing + // at the moment. 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. @@ -467,7 +436,7 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { printer->Print( "\n" - "typedef struct $classname$_Storage {\n" + "typedef struct $classname$__storage_ {\n" " uint32_t _has_storage_[$sizeof_has_storage$];\n", "classname", class_name_, "sizeof_has_storage", SimpleItoa(sizeof_has_storage)); @@ -479,14 +448,14 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { } printer->Outdent(); - printer->Print("} $classname$_Storage;\n\n", "classname", class_name_); + 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" + " static GPBDescriptor *descriptor = nil;\n" " if (!descriptor) {\n"); bool has_oneofs = oneof_generators_.size(); @@ -507,30 +476,45 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { " };\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()); + bool has_fields = descriptor_->field_count() > 0; + if (has_fields) { + // TODO(thomasvl): The plugin's FieldGenerator::GenerateFieldDescription() + // wraps the fieldOptions's value of this structure in an CPP gate so + // they can be compiled away; but that still results in a const char* in + // the structure for a NULL pointer for every message field. If the + // fieldOptions are moved to a separate payload like the TextFormat extra + // data is, then it would shrink that static data shrinking the binaries + // a little more. + // TODO(thomasvl): proto3 syntax doens't need a defaultValue in the + // structure because primitive types are always zero. If we add a second + // structure and a different initializer, we can avoid the wasted static + // storage for every field in a proto3 message. + printer->Print( + " static GPBMessageFieldDescription fields[] = {\n"); + printer->Indent(); + printer->Indent(); + printer->Indent(); + 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(); + printer->Print( + " };\n"); } - 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(); @@ -543,12 +527,13 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { printer->Outdent(); printer->Outdent(); printer->Outdent(); + printer->Print( + " };\n"); } bool has_extensions = sorted_extensions.size(); if (has_extensions) { printer->Print( - " };\n" " static GPBExtensionRange ranges[] = {\n"); printer->Indent(); printer->Indent(); @@ -561,11 +546,16 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { printer->Outdent(); printer->Outdent(); printer->Outdent(); + printer->Print( + " };\n"); } map<string, string> vars; vars["classname"] = class_name_; vars["rootclassname"] = root_classname_; + vars["fields"] = has_fields ? "fields" : "NULL"; + vars["fields_count"] = + has_fields ? "sizeof(fields) / sizeof(GPBMessageFieldDescription)" : "0"; vars["oneofs"] = has_oneofs ? "oneofs" : "NULL"; vars["oneof_count"] = has_oneofs ? "sizeof(oneofs) / sizeof(GPBMessageOneofDescription)" : "0"; @@ -578,23 +568,23 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { 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"); + " GPBDescriptor *localDescriptor =\n" + " [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n" + " rootClass:[$rootclassname$ class]\n" + " file:$rootclassname$_FileDescriptor()\n" + " fields:$fields$\n" + " fieldCount:$fields_count$\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( @@ -604,26 +594,29 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { "#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"); + " GPBDescriptor *localDescriptor =\n" + " [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n" + " rootClass:[$rootclassname$ class]\n" + " file:$rootclassname$_FileDescriptor()\n" + " fields:$fields$\n" + " fieldCount:$fields_count$\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"); + " NSAssert(descriptor == nil, @\"Startup recursed!\");\n" + " descriptor = localDescriptor;\n" + " }\n" + " return descriptor;\n" + "}\n\n" + "@end\n\n"); for (int i = 0; i < descriptor_->field_count(); i++) { field_generators_.get(descriptor_->field(i)) diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.h b/src/google/protobuf/compiler/objectivec/objectivec_message.h index 8d03c0b8..06b536ff 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.h @@ -57,20 +57,13 @@ class MessageGenerator { MessageGenerator(const string& root_classname, const Descriptor* descriptor); ~MessageGenerator(); - void GenerateStaticVariablesInitialization(io::Printer* printer, - bool* out_generated); + void GenerateStaticVariablesInitialization(io::Printer* printer); void GenerateEnumHeader(io::Printer* printer); void GenerateMessageHeader(io::Printer* printer); void GenerateSource(io::Printer* printer); void GenerateExtensionRegistrationSource(io::Printer* printer); void DetermineForwardDeclarations(set<string>* fwd_decls); - // 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); @@ -87,8 +80,6 @@ class MessageGenerator { 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_; diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc index 2e3bdfdb..f2ce4e5b 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc @@ -53,7 +53,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["group_or_message"] = (descriptor->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message"; - (*variables)["typeSpecific_value"] = "GPBStringifySymbol(" + message_type + ")"; + (*variables)["dataTypeSpecific_value"] = "GPBStringifySymbol(" + message_type + ")"; } } // namespace diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index 344ed450..e7890fae 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -913,7 +913,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes( int CodeGeneratorResponse_File::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 7) { + if (_has_bits_[0 / 32] & 7u) { // optional string name = 1; if (has_name()) { total_size += 1 + diff --git a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc index 6c203ab6..1b04cb32 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc @@ -47,6 +47,7 @@ namespace { string FindRubyTestDir(const string& file) { // Inspired by TestSourceDir() in src/google/protobuf/testing/googletest.cc. +#ifndef GOOGLE_THIRD_PARTY_PROTOBUF string prefix = "."; while (!File::Exists(prefix + "/src/google/protobuf/compiler/ruby" + file)) { if (!File::Exists(prefix)) { @@ -57,6 +58,9 @@ string FindRubyTestDir(const string& file) { prefix += "/.."; } return prefix + "/src/google/protobuf/compiler/ruby"; +#else + return "third_party/protobuf/src/google/protobuf/compiler/ruby"; +#endif // GOOGLE_THIRD_PARTY_PROTOBUF } // This test is a simple golden-file test over the output of the Ruby code diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc index 61ae4381..a3cff1f8 100644 --- a/src/google/protobuf/compiler/subprocess.cc +++ b/src/google/protobuf/compiler/subprocess.cc @@ -171,7 +171,7 @@ bool Subprocess::Communicate(const Message& input, Message* output, DWORD wait_result = WaitForMultipleObjects(handle_count, handles, FALSE, INFINITE); - HANDLE signaled_handle; + HANDLE signaled_handle = NULL; if (wait_result >= WAIT_OBJECT_0 && wait_result < WAIT_OBJECT_0 + handle_count) { signaled_handle = handles[wait_result - WAIT_OBJECT_0]; diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 755c2617..30b3a3a7 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -753,9 +753,10 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "ion\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004sp" "an\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022\031" "\n\021trailing_comments\030\004 \001(\t\022!\n\031leading_det" - "ached_comments\030\006 \003(\tBY\n\023com.google.proto" - "bufB\020DescriptorProtosH\001\242\002\003GPB\252\002\'Google.P" - "rotocolBuffers.DescriptorProtos", 4951); + "ached_comments\030\006 \003(\tBe\n\023com.google.proto" + "bufB\020DescriptorProtosH\001Z\ndescriptor\242\002\003GP" + "B\252\002\'Google.ProtocolBuffers.DescriptorPro" + "tos", 4963); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/descriptor.proto", &protobuf_RegisterTypes); FileDescriptorSet::default_instance_ = new FileDescriptorSet(); @@ -1648,7 +1649,7 @@ void FileDescriptorProto::SerializeWithCachedSizes( int FileDescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 3) { + if (_has_bits_[0 / 32] & 3u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -1664,7 +1665,7 @@ int FileDescriptorProto::ByteSize() const { } } - if (_has_bits_[9 / 32] & 3584) { + if (_has_bits_[9 / 32] & 3584u) { // optional .google.protobuf.FileOptions options = 8; if (has_options()) { total_size += 1 + @@ -2534,7 +2535,7 @@ void DescriptorProto_ExtensionRange::SerializeWithCachedSizes( int DescriptorProto_ExtensionRange::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 3) { + if (_has_bits_[0 / 32] & 3u) { // optional int32 start = 1; if (has_start()) { total_size += 1 + @@ -2817,7 +2818,7 @@ void DescriptorProto_ReservedRange::SerializeWithCachedSizes( int DescriptorProto_ReservedRange::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 3) { + if (_has_bits_[0 / 32] & 3u) { // optional int32 start = 1; if (has_start()) { total_size += 1 + @@ -3373,7 +3374,7 @@ void DescriptorProto::SerializeWithCachedSizes( int DescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 129) { + if (_has_bits_[0 / 32] & 129u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -4558,7 +4559,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes( int FieldDescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 255) { + if (_has_bits_[0 / 32] & 255u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -5633,7 +5634,7 @@ void EnumDescriptorProto::SerializeWithCachedSizes( int EnumDescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 5) { + if (_has_bits_[0 / 32] & 5u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -6102,7 +6103,7 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes( int EnumValueDescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 7) { + if (_has_bits_[0 / 32] & 7u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -6569,7 +6570,7 @@ void ServiceDescriptorProto::SerializeWithCachedSizes( int ServiceDescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 5) { + if (_has_bits_[0 / 32] & 5u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -7165,7 +7166,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes( int MethodDescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 63) { + if (_has_bits_[0 / 32] & 63u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -8240,7 +8241,7 @@ void FileOptions::SerializeWithCachedSizes( int FileOptions::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 255) { + if (_has_bits_[0 / 32] & 255u) { // optional string java_package = 1; if (has_java_package()) { total_size += 1 + @@ -8289,7 +8290,7 @@ int FileOptions::ByteSize() const { } } - if (_has_bits_[8 / 32] & 16128) { + if (_has_bits_[8 / 32] & 16128u) { // optional bool java_generic_services = 17 [default = false]; if (has_java_generic_services()) { total_size += 2 + 1; @@ -9279,7 +9280,7 @@ void MessageOptions::SerializeWithCachedSizes( int MessageOptions::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 15) { + if (_has_bits_[0 / 32] & 15u) { // optional bool message_set_wire_format = 1 [default = false]; if (has_message_set_wire_format()) { total_size += 1 + 1; @@ -9939,7 +9940,7 @@ void FieldOptions::SerializeWithCachedSizes( int FieldOptions::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 63) { + if (_has_bits_[0 / 32] & 63u) { // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; if (has_ctype()) { total_size += 1 + @@ -10498,7 +10499,7 @@ void EnumOptions::SerializeWithCachedSizes( int EnumOptions::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 3) { + if (_has_bits_[0 / 32] & 3u) { // optional bool allow_alias = 2; if (has_allow_alias()) { total_size += 1 + 1; @@ -12410,7 +12411,7 @@ void UninterpretedOption::SerializeWithCachedSizes( int UninterpretedOption::ByteSize() const { int total_size = 0; - if (_has_bits_[1 / 32] & 126) { + if (_has_bits_[1 / 32] & 126u) { // optional string identifier_value = 3; if (has_identifier_value()) { total_size += 1 + @@ -13248,7 +13249,7 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes( int SourceCodeInfo_Location::ByteSize() const { int total_size = 0; - if (_has_bits_[2 / 32] & 12) { + if (_has_bits_[2 / 32] & 12u) { // optional string leading_comments = 3; if (has_leading_comments()) { total_size += 1 + diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index 20a60080..13f136cb 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -40,6 +40,7 @@ syntax = "proto2"; package google.protobuf; +option go_package = "descriptor"; option java_package = "com.google.protobuf"; option java_outer_classname = "DescriptorProtos"; option csharp_namespace = "Google.ProtocolBuffers.DescriptorProtos"; diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc index c9f4ca7f..dd7c036e 100644 --- a/src/google/protobuf/io/gzip_stream.cc +++ b/src/google/protobuf/io/gzip_stream.cc @@ -33,8 +33,6 @@ // This file contains the implementation of classes GzipInputStream and // GzipOutputStream. -#include "config.h" - #if HAVE_ZLIB #include <google/protobuf/io/gzip_stream.h> diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc index dd3d1285..f2e5b629 100644 --- a/src/google/protobuf/io/zero_copy_stream_unittest.cc +++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc @@ -46,8 +46,6 @@ // "parametized tests" so that one set of tests can be used on all the // implementations. -#include "config.h" - #ifdef _MSC_VER #include <io.h> #else diff --git a/src/google/protobuf/stubs/atomicops.h b/src/google/protobuf/stubs/atomicops.h index bbe2d845..cd20caac 100644 --- a/src/google/protobuf/stubs/atomicops.h +++ b/src/google/protobuf/stubs/atomicops.h @@ -56,6 +56,7 @@ // Don't include this file for people not concerned about thread safety. #ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY +#include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/platform_macros.h> namespace google { diff --git a/src/google/protobuf/stubs/bytestream.cc b/src/google/protobuf/stubs/bytestream.cc new file mode 100644 index 00000000..f4af6a50 --- /dev/null +++ b/src/google/protobuf/stubs/bytestream.cc @@ -0,0 +1,196 @@ +// 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/stubs/bytestream.h> + +#include <string.h> +#include <algorithm> + +namespace google { +namespace protobuf { +namespace strings { + +void ByteSource::CopyTo(ByteSink* sink, size_t n) { + while (n > 0) { + StringPiece fragment = Peek(); + if (fragment.empty()) { + GOOGLE_LOG(DFATAL) << "ByteSource::CopyTo() overran input."; + break; + } + std::size_t fragment_size = std::min<std::size_t>(n, fragment.size()); + sink->Append(fragment.data(), fragment_size); + Skip(fragment_size); + n -= fragment_size; + } +} + +void ByteSink::Flush() {} + +void UncheckedArrayByteSink::Append(const char* data, size_t n) { + if (data != dest_) { + // Catch cases where the pointer returned by GetAppendBuffer() was modified. + GOOGLE_DCHECK(!(dest_ <= data && data < (dest_ + n))) + << "Append() data[] overlaps with dest_[]"; + memcpy(dest_, data, n); + } + dest_ += n; +} + +CheckedArrayByteSink::CheckedArrayByteSink(char* outbuf, size_t capacity) + : outbuf_(outbuf), capacity_(capacity), size_(0), overflowed_(false) { +} + +void CheckedArrayByteSink::Append(const char* bytes, size_t n) { + size_t available = capacity_ - size_; + if (n > available) { + n = available; + overflowed_ = true; + } + if (n > 0 && bytes != (outbuf_ + size_)) { + // Catch cases where the pointer returned by GetAppendBuffer() was modified. + GOOGLE_DCHECK(!(outbuf_ <= bytes && bytes < (outbuf_ + capacity_))) + << "Append() bytes[] overlaps with outbuf_[]"; + memcpy(outbuf_ + size_, bytes, n); + } + size_ += n; +} + +GrowingArrayByteSink::GrowingArrayByteSink(size_t estimated_size) + : capacity_(estimated_size), + buf_(new char[estimated_size]), + size_(0) { +} + +GrowingArrayByteSink::~GrowingArrayByteSink() { + delete[] buf_; // Just in case the user didn't call GetBuffer. +} + +void GrowingArrayByteSink::Append(const char* bytes, size_t n) { + size_t available = capacity_ - size_; + if (bytes != (buf_ + size_)) { + // Catch cases where the pointer returned by GetAppendBuffer() was modified. + // We need to test for this before calling Expand() which may reallocate. + GOOGLE_DCHECK(!(buf_ <= bytes && bytes < (buf_ + capacity_))) + << "Append() bytes[] overlaps with buf_[]"; + } + if (n > available) { + Expand(n - available); + } + if (n > 0 && bytes != (buf_ + size_)) { + memcpy(buf_ + size_, bytes, n); + } + size_ += n; +} + +char* GrowingArrayByteSink::GetBuffer(size_t* nbytes) { + ShrinkToFit(); + char* b = buf_; + *nbytes = size_; + buf_ = NULL; + size_ = capacity_ = 0; + return b; +} + +void GrowingArrayByteSink::Expand(size_t amount) { // Expand by at least 50%. + size_t new_capacity = std::max(capacity_ + amount, (3 * capacity_) / 2); + char* bigger = new char[new_capacity]; + memcpy(bigger, buf_, size_); + delete[] buf_; + buf_ = bigger; + capacity_ = new_capacity; +} + +void GrowingArrayByteSink::ShrinkToFit() { + // Shrink only if the buffer is large and size_ is less than 3/4 + // of capacity_. + if (capacity_ > 256 && size_ < (3 * capacity_) / 4) { + char* just_enough = new char[size_]; + memcpy(just_enough, buf_, size_); + delete[] buf_; + buf_ = just_enough; + capacity_ = size_; + } +} + +void StringByteSink::Append(const char* data, size_t n) { + dest_->append(data, n); +} + +size_t ArrayByteSource::Available() const { + return input_.size(); +} + +StringPiece ArrayByteSource::Peek() { + return input_; +} + +void ArrayByteSource::Skip(size_t n) { + GOOGLE_DCHECK_LE(n, input_.size()); + input_.remove_prefix(n); +} + +LimitByteSource::LimitByteSource(ByteSource *source, size_t limit) + : source_(source), + limit_(limit) { +} + +size_t LimitByteSource::Available() const { + size_t available = source_->Available(); + if (available > limit_) { + available = limit_; + } + + return available; +} + +StringPiece LimitByteSource::Peek() { + StringPiece piece(source_->Peek()); + if (piece.size() > limit_) { + piece.set(piece.data(), limit_); + } + + return piece; +} + +void LimitByteSource::Skip(size_t n) { + GOOGLE_DCHECK_LE(n, limit_); + source_->Skip(n); + limit_ -= n; +} + +void LimitByteSource::CopyTo(ByteSink *sink, size_t n) { + GOOGLE_DCHECK_LE(n, limit_); + source_->CopyTo(sink, n); + limit_ -= n; +} + +} // namespace strings +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/bytestream.h b/src/google/protobuf/stubs/bytestream.h new file mode 100644 index 00000000..de8e0204 --- /dev/null +++ b/src/google/protobuf/stubs/bytestream.h @@ -0,0 +1,348 @@ +// 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 file declares the ByteSink and ByteSource abstract interfaces. These +// interfaces represent objects that consume (ByteSink) or produce (ByteSource) +// a sequence of bytes. Using these abstract interfaces in your APIs can help +// make your code work with a variety of input and output types. +// +// This file also declares the following commonly used implementations of these +// interfaces. +// +// ByteSink: +// UncheckedArrayByteSink Writes to an array, without bounds checking +// CheckedArrayByteSink Writes to an array, with bounds checking +// GrowingArrayByteSink Allocates and writes to a growable buffer +// StringByteSink Writes to an STL string +// NullByteSink Consumes a never-ending stream of bytes +// +// ByteSource: +// ArrayByteSource Reads from an array or string/StringPiece +// LimitedByteSource Limits the number of bytes read from an + +#ifndef GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_ +#define GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_ + +#include <stddef.h> +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/stringpiece.h> + +class CordByteSink; +class MemBlock; + +namespace google { +namespace protobuf { +namespace strings { + +// An abstract interface for an object that consumes a sequence of bytes. This +// interface offers 3 different ways to append data, and a Flush() function. +// +// Example: +// +// string my_data; +// ... +// ByteSink* sink = ... +// sink->Append(my_data.data(), my_data.size()); +// sink->Flush(); +// +class LIBPROTOBUF_EXPORT ByteSink { + public: + ByteSink() {} + virtual ~ByteSink() {} + + // Appends the "n" bytes starting at "bytes". + virtual void Append(const char* bytes, size_t n) = 0; + + // Flushes internal buffers. The default implemenation does nothing. ByteSink + // subclasses may use internal buffers that require calling Flush() at the end + // of the stream. + virtual void Flush(); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSink); +}; + +// An abstract interface for an object that produces a fixed-size sequence of +// bytes. +// +// Example: +// +// ByteSource* source = ... +// while (source->Available() > 0) { +// StringPiece data = source->Peek(); +// ... do something with "data" ... +// source->Skip(data.length()); +// } +// +class LIBPROTOBUF_EXPORT ByteSource { + public: + ByteSource() {} + virtual ~ByteSource() {} + + // Returns the number of bytes left to read from the source. Available() + // should decrease by N each time Skip(N) is called. Available() may not + // increase. Available() returning 0 indicates that the ByteSource is + // exhausted. + // + // Note: Size() may have been a more appropriate name as it's more + // indicative of the fixed-size nature of a ByteSource. + virtual size_t Available() const = 0; + + // Returns a StringPiece of the next contiguous region of the source. Does not + // reposition the source. The returned region is empty iff Available() == 0. + // + // The returned region is valid until the next call to Skip() or until this + // object is destroyed, whichever occurs first. + // + // The length of the returned StringPiece will be <= Available(). + virtual StringPiece Peek() = 0; + + // Skips the next n bytes. Invalidates any StringPiece returned by a previous + // call to Peek(). + // + // REQUIRES: Available() >= n + virtual void Skip(size_t n) = 0; + + // Writes the next n bytes in this ByteSource to the given ByteSink, and + // advances this ByteSource past the copied bytes. The default implementation + // of this method just copies the bytes normally, but subclasses might + // override CopyTo to optimize certain cases. + // + // REQUIRES: Available() >= n + virtual void CopyTo(ByteSink* sink, size_t n); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSource); +}; + +// +// Some commonly used implementations of ByteSink +// + +// Implementation of ByteSink that writes to an unsized byte array. No +// bounds-checking is performed--it is the caller's responsibility to ensure +// that the destination array is large enough. +// +// Example: +// +// char buf[10]; +// UncheckedArrayByteSink sink(buf); +// sink.Append("hi", 2); // OK +// sink.Append(data, 100); // WOOPS! Overflows buf[10]. +// +class LIBPROTOBUF_EXPORT UncheckedArrayByteSink : public ByteSink { + public: + explicit UncheckedArrayByteSink(char* dest) : dest_(dest) {} + virtual void Append(const char* data, size_t n); + + // Returns the current output pointer so that a caller can see how many bytes + // were produced. + // + // Note: this method is not part of the ByteSink interface. + char* CurrentDestination() const { return dest_; } + + private: + char* dest_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UncheckedArrayByteSink); +}; + +// Implementation of ByteSink that writes to a sized byte array. This sink will +// not write more than "capacity" bytes to outbuf. Once "capacity" bytes are +// appended, subsequent bytes will be ignored and Overflowed() will return true. +// Overflowed() does not cause a runtime error (i.e., it does not CHECK fail). +// +// Example: +// +// char buf[10]; +// CheckedArrayByteSink sink(buf, 10); +// sink.Append("hi", 2); // OK +// sink.Append(data, 100); // Will only write 8 more bytes +// +class LIBPROTOBUF_EXPORT CheckedArrayByteSink : public ByteSink { + public: + CheckedArrayByteSink(char* outbuf, size_t capacity); + virtual void Append(const char* bytes, size_t n); + + // Returns the number of bytes actually written to the sink. + size_t NumberOfBytesWritten() const { return size_; } + + // Returns true if any bytes were discarded, i.e., if there was an + // attempt to write more than 'capacity' bytes. + bool Overflowed() const { return overflowed_; } + + private: + char* outbuf_; + const size_t capacity_; + size_t size_; + bool overflowed_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CheckedArrayByteSink); +}; + +// Implementation of ByteSink that allocates an internal buffer (a char array) +// and expands it as needed to accomodate appended data (similar to a string), +// and allows the caller to take ownership of the internal buffer via the +// GetBuffer() method. The buffer returned from GetBuffer() must be deleted by +// the caller with delete[]. GetBuffer() also sets the internal buffer to be +// empty, and subsequent appends to the sink will create a new buffer. The +// destructor will free the internal buffer if GetBuffer() was not called. +// +// Example: +// +// GrowingArrayByteSink sink(10); +// sink.Append("hi", 2); +// sink.Append(data, n); +// const char* buf = sink.GetBuffer(); // Ownership transferred +// delete[] buf; +// +class LIBPROTOBUF_EXPORT GrowingArrayByteSink : public strings::ByteSink { + public: + explicit GrowingArrayByteSink(size_t estimated_size); + virtual ~GrowingArrayByteSink(); + virtual void Append(const char* bytes, size_t n); + + // Returns the allocated buffer, and sets nbytes to its size. The caller takes + // ownership of the buffer and must delete it with delete[]. + char* GetBuffer(size_t* nbytes); + + private: + void Expand(size_t amount); + void ShrinkToFit(); + + size_t capacity_; + char* buf_; + size_t size_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GrowingArrayByteSink); +}; + +// Implementation of ByteSink that appends to the given string. +// Existing contents of "dest" are not modified; new data is appended. +// +// Example: +// +// string dest = "Hello "; +// StringByteSink sink(&dest); +// sink.Append("World", 5); +// assert(dest == "Hello World"); +// +class LIBPROTOBUF_EXPORT StringByteSink : public ByteSink { + public: + explicit StringByteSink(string* dest) : dest_(dest) {} + virtual void Append(const char* data, size_t n); + + private: + string* dest_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringByteSink); +}; + +// Implementation of ByteSink that discards all data. +// +// Example: +// +// NullByteSink sink; +// sink.Append(data, data.size()); // All data ignored. +// +class LIBPROTOBUF_EXPORT NullByteSink : public ByteSink { + public: + NullByteSink() {} + virtual void Append(const char *data, size_t n) {} + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(NullByteSink); +}; + +// +// Some commonly used implementations of ByteSource +// + +// Implementation of ByteSource that reads from a StringPiece. +// +// Example: +// +// string data = "Hello"; +// ArrayByteSource source(data); +// assert(source.Available() == 5); +// assert(source.Peek() == "Hello"); +// +class LIBPROTOBUF_EXPORT ArrayByteSource : public ByteSource { + public: + explicit ArrayByteSource(StringPiece s) : input_(s) {} + + virtual size_t Available() const; + virtual StringPiece Peek(); + virtual void Skip(size_t n); + + private: + StringPiece input_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayByteSource); +}; + +// Implementation of ByteSource that wraps another ByteSource, limiting the +// number of bytes returned. +// +// The caller maintains ownership of the underlying source, and may not use the +// underlying source while using the LimitByteSource object. The underlying +// source's pointer is advanced by n bytes every time this LimitByteSource +// object is advanced by n. +// +// Example: +// +// string data = "Hello World"; +// ArrayByteSource abs(data); +// assert(abs.Available() == data.size()); +// +// LimitByteSource limit(abs, 5); +// assert(limit.Available() == 5); +// assert(limit.Peek() == "Hello"); +// +class LIBPROTOBUF_EXPORT LimitByteSource : public ByteSource { + public: + // Returns at most "limit" bytes from "source". + LimitByteSource(ByteSource* source, size_t limit); + + virtual size_t Available() const; + virtual StringPiece Peek(); + virtual void Skip(size_t n); + + // We override CopyTo so that we can forward to the underlying source, in + // case it has an efficient implementation of CopyTo. + virtual void CopyTo(ByteSink* sink, size_t n); + + private: + ByteSource* source_; + size_t limit_; +}; + +} // namespace strings +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_ diff --git a/src/google/protobuf/stubs/bytestream_unittest.cc b/src/google/protobuf/stubs/bytestream_unittest.cc new file mode 100644 index 00000000..06f114ab --- /dev/null +++ b/src/google/protobuf/stubs/bytestream_unittest.cc @@ -0,0 +1,146 @@ +// 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/stubs/bytestream.h> + +#include <stdio.h> +#include <string.h> +#include <algorithm> + +#include <google/protobuf/testing/googletest.h> +#include <gtest/gtest.h> + +namespace google { +namespace protobuf { +namespace strings { +namespace { + +// We use this class instead of ArrayByteSource to simulate a ByteSource that +// contains multiple fragments. ArrayByteSource returns the entire array in +// one fragment. +class MockByteSource : public ByteSource { + public: + MockByteSource(StringPiece data, int block_size) + : data_(data), block_size_(block_size) {} + + size_t Available() const { return data_.size(); } + StringPiece Peek() { + return data_.substr(0, block_size_); + } + void Skip(size_t n) { data_.remove_prefix(n); } + + private: + StringPiece data_; + int block_size_; +}; + +TEST(ByteSourceTest, CopyTo) { + StringPiece data("Hello world!"); + MockByteSource source(data, 3); + string str; + StringByteSink sink(&str); + + source.CopyTo(&sink, data.size()); + EXPECT_EQ(data, str); +} + +TEST(ByteSourceTest, CopySubstringTo) { + StringPiece data("Hello world!"); + MockByteSource source(data, 3); + source.Skip(1); + string str; + StringByteSink sink(&str); + + source.CopyTo(&sink, data.size() - 2); + EXPECT_EQ(data.substr(1, data.size() - 2), str); + EXPECT_EQ("!", source.Peek()); +} + +TEST(ByteSourceTest, LimitByteSource) { + StringPiece data("Hello world!"); + MockByteSource source(data, 3); + LimitByteSource limit_source(&source, 6); + EXPECT_EQ(6, limit_source.Available()); + limit_source.Skip(1); + EXPECT_EQ(5, limit_source.Available()); + + { + string str; + StringByteSink sink(&str); + limit_source.CopyTo(&sink, limit_source.Available()); + EXPECT_EQ("ello ", str); + EXPECT_EQ(0, limit_source.Available()); + EXPECT_EQ(6, source.Available()); + } + + { + string str; + StringByteSink sink(&str); + source.CopyTo(&sink, source.Available()); + EXPECT_EQ("world!", str); + EXPECT_EQ(0, source.Available()); + } +} + +TEST(ByteSourceTest, CopyToStringByteSink) { + StringPiece data("Hello world!"); + MockByteSource source(data, 3); + string str; + StringByteSink sink(&str); + source.CopyTo(&sink, data.size()); + EXPECT_EQ(data, str); +} + +// Verify that ByteSink is subclassable and Flush() overridable. +class FlushingByteSink : public StringByteSink { + public: + explicit FlushingByteSink(string* dest) : StringByteSink(dest) {} + virtual void Flush() { Append("z", 1); } + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FlushingByteSink); +}; + +// Write and Flush via the ByteSink superclass interface. +void WriteAndFlush(ByteSink* s) { + s->Append("abc", 3); + s->Flush(); +} + +TEST(ByteSinkTest, Flush) { + string str; + FlushingByteSink f_sink(&str); + WriteAndFlush(&f_sink); + EXPECT_STREQ("abcz", str.c_str()); +} + +} // namespace +} // namespace strings +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/casts.h b/src/google/protobuf/stubs/casts.h index cccf65a1..be652849 100644 --- a/src/google/protobuf/stubs/casts.h +++ b/src/google/protobuf/stubs/casts.h @@ -111,12 +111,22 @@ inline To down_cast(From& f) { return *static_cast<ToAsPointer>(&f); } +template<typename To, typename From> +inline To bit_cast(const From& from) { + GOOGLE_COMPILE_ASSERT(sizeof(From) == sizeof(To), + bit_cast_with_different_sizes); + To dest; + memcpy(&dest, &from, sizeof(dest)); + return dest; +} + } // namespace internal // We made these internal so that they would show up as such in the docs, // but we don't want to stick "internal::" in front of them everywhere. using internal::implicit_cast; using internal::down_cast; +using internal::bit_cast; } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc index 54e00ccb..d470fc72 100644 --- a/src/google/protobuf/stubs/common.cc +++ b/src/google/protobuf/stubs/common.cc @@ -32,12 +32,13 @@ #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/once.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/stringpiece.h> +#include <google/protobuf/stubs/strutil.h> #include <stdio.h> #include <errno.h> #include <vector> -#include "config.h" - #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN // We only need minimal includes #include <windows.h> @@ -148,6 +149,27 @@ LogMessage& LogMessage::operator<<(const char* value) { return *this; } +LogMessage& LogMessage::operator<<(const StringPiece& value) { + message_ += value.ToString(); + return *this; +} + +LogMessage& LogMessage::operator<<(long long value) { + message_ += SimpleItoa(value); + return *this; +} + +LogMessage& LogMessage::operator<<(unsigned long long value) { + message_ += SimpleItoa(value); + return *this; +} + +LogMessage& LogMessage::operator<<( + const ::google::protobuf::util::Status& status) { + message_ += status.ToString(); + return *this; +} + // Since this is just for logging, we don't care if the current locale changes // the results -- in fact, we probably prefer that. So we use snprintf() // instead of Simple*toa(). @@ -167,7 +189,7 @@ LogMessage& LogMessage::operator<<(const char* value) { DECLARE_STREAM_OPERATOR(char , "%c" ) DECLARE_STREAM_OPERATOR(int , "%d" ) -DECLARE_STREAM_OPERATOR(uint , "%u" ) +DECLARE_STREAM_OPERATOR(unsigned int , "%u" ) DECLARE_STREAM_OPERATOR(long , "%ld") DECLARE_STREAM_OPERATOR(unsigned long, "%lu") DECLARE_STREAM_OPERATOR(double , "%g" ) diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h index 3acaeba1..c3620146 100644 --- a/src/google/protobuf/stubs/common.h +++ b/src/google/protobuf/stubs/common.h @@ -48,6 +48,26 @@ #include <stdint.h> #endif +#undef PROTOBUF_LITTLE_ENDIAN +#ifdef _MSC_VER + // Assuming windows is always little-endian. + #if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + #define PROTOBUF_LITTLE_ENDIAN 1 + #endif + #if _MSC_VER >= 1300 + // If MSVC has "/RTCc" set, it will complain about truncating casts at + // runtime. This file contains some intentional truncating casts. + #pragma runtime_checks("c", off) + #endif +#else + #include <sys/param.h> // __BYTE_ORDER + #if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \ + (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN)) && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + #define PROTOBUF_LITTLE_ENDIAN 1 + #endif +#endif + #ifndef PROTOBUF_USE_EXCEPTIONS #if defined(_MSC_VER) && defined(_CPPUNWIND) #define PROTOBUF_USE_EXCEPTIONS 1 @@ -62,6 +82,8 @@ #include <exception> #endif +#include <google/protobuf/stubs/platform_macros.h> + #if defined(__APPLE__) #include <TargetConditionals.h> // for TARGET_OS_IPHONE #endif @@ -98,6 +120,12 @@ namespace protobuf { TypeName(const TypeName&); \ void operator=(const TypeName&) +#undef GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS +#define GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ + TypeName(); \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + #if defined(_MSC_VER) && defined(PROTOBUF_USE_DLLS) #ifdef LIBPROTOBUF_EXPORTS #define LIBPROTOBUF_EXPORT __declspec(dllexport) @@ -258,7 +286,7 @@ static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF); #ifndef GOOGLE_PREDICT_FALSE #ifdef __GNUC__ // Provided at least since GCC 3.0. -#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(!!(x), 1)) +#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0)) #else #define GOOGLE_PREDICT_FALSE #endif @@ -658,6 +686,10 @@ enum LogLevel { #endif }; +class StringPiece; +namespace util { +class Status; +} namespace internal { class LogFinisher; @@ -671,11 +703,15 @@ class LIBPROTOBUF_EXPORT LogMessage { LogMessage& operator<<(const char* value); LogMessage& operator<<(char value); LogMessage& operator<<(int value); - LogMessage& operator<<(uint value); + LogMessage& operator<<(unsigned int value); LogMessage& operator<<(long value); LogMessage& operator<<(unsigned long value); + LogMessage& operator<<(long long value); + LogMessage& operator<<(unsigned long long value); LogMessage& operator<<(double value); LogMessage& operator<<(void* value); + LogMessage& operator<<(const StringPiece& value); + LogMessage& operator<<(const ::google::protobuf::util::Status& status); private: friend class LogFinisher; @@ -694,6 +730,11 @@ class LIBPROTOBUF_EXPORT LogFinisher { void operator=(LogMessage& other); }; +template<typename T> +bool IsOk(T status) { return status.ok(); } +template<> +inline bool IsOk(bool status) { return status; } + } // namespace internal // Undef everything in case we're being mixed with some other Google library @@ -715,6 +756,7 @@ class LIBPROTOBUF_EXPORT LogFinisher { #undef GOOGLE_DLOG #undef GOOGLE_DCHECK +#undef GOOGLE_DCHECK_OK #undef GOOGLE_DCHECK_EQ #undef GOOGLE_DCHECK_NE #undef GOOGLE_DCHECK_LT @@ -731,7 +773,7 @@ class LIBPROTOBUF_EXPORT LogFinisher { #define GOOGLE_CHECK(EXPRESSION) \ GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": " -#define GOOGLE_CHECK_OK(A) GOOGLE_CHECK(A) +#define GOOGLE_CHECK_OK(A) GOOGLE_CHECK(::google::protobuf::internal::IsOk(A)) #define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK((A) == (B)) #define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK((A) != (B)) #define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK((A) < (B)) @@ -758,6 +800,7 @@ T* CheckNotNull(const char* /* file */, int /* line */, #define GOOGLE_DLOG GOOGLE_LOG_IF(INFO, false) #define GOOGLE_DCHECK(EXPRESSION) while(false) GOOGLE_CHECK(EXPRESSION) +#define GOOGLE_DCHECK_OK(E) GOOGLE_DCHECK(::google::protobuf::internal::IsOk(E)) #define GOOGLE_DCHECK_EQ(A, B) GOOGLE_DCHECK((A) == (B)) #define GOOGLE_DCHECK_NE(A, B) GOOGLE_DCHECK((A) != (B)) #define GOOGLE_DCHECK_LT(A, B) GOOGLE_DCHECK((A) < (B)) @@ -770,6 +813,7 @@ T* CheckNotNull(const char* /* file */, int /* line */, #define GOOGLE_DLOG GOOGLE_LOG #define GOOGLE_DCHECK GOOGLE_CHECK +#define GOOGLE_DCHECK_OK GOOGLE_CHECK_OK #define GOOGLE_DCHECK_EQ GOOGLE_CHECK_EQ #define GOOGLE_DCHECK_NE GOOGLE_CHECK_NE #define GOOGLE_DCHECK_LT GOOGLE_CHECK_LT @@ -881,6 +925,30 @@ class LIBPROTOBUF_EXPORT Closure { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Closure); }; +template<typename R, typename A1> +class LIBPROTOBUF_EXPORT ResultCallback1 { + public: + ResultCallback1() {} + virtual ~ResultCallback1() {} + + virtual R Run(A1) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback1); +}; + +template<typename R, typename A1, typename A2> +class LIBPROTOBUF_EXPORT ResultCallback2 { + public: + ResultCallback2() {} + virtual ~ResultCallback2() {} + + virtual R Run(A1,A2) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback2); +}; + namespace internal { class LIBPROTOBUF_EXPORT FunctionClosure0 : public Closure { @@ -1019,6 +1087,96 @@ class MethodClosure2 : public Closure { Arg2 arg2_; }; +template<typename R, typename Arg1> +class FunctionResultCallback_0_1 : public ResultCallback1<R, Arg1> { + public: + typedef R (*FunctionType)(Arg1 arg1); + + FunctionResultCallback_0_1(FunctionType function, bool self_deleting) + : function_(function), self_deleting_(self_deleting) {} + ~FunctionResultCallback_0_1() {} + + R Run(Arg1 a1) { + bool needs_delete = self_deleting_; // read in case callback deletes + R result = function_(a1); + if (needs_delete) delete this; + return result; + } + + private: + FunctionType function_; + bool self_deleting_; +}; + +template<typename R, typename P1, typename A1> +class FunctionResultCallback_1_1 : public ResultCallback1<R, A1> { + public: + typedef R (*FunctionType)(P1, A1); + + FunctionResultCallback_1_1(FunctionType function, bool self_deleting, + P1 p1) + : function_(function), self_deleting_(self_deleting), p1_(p1) {} + ~FunctionResultCallback_1_1() {} + + R Run(A1 a1) { + bool needs_delete = self_deleting_; // read in case callback deletes + R result = function_(p1_, a1); + if (needs_delete) delete this; + return result; + } + + private: + FunctionType function_; + bool self_deleting_; + P1 p1_; +}; + +// Duplicate this again in the type_traits.h, due to dependency problems. +template <class T> struct internal_remove_reference; +template<typename T> struct internal_remove_reference { typedef T type; }; +template<typename T> struct internal_remove_reference<T&> { typedef T type; }; + +template <typename T> +struct InternalConstRef { + typedef typename internal_remove_reference<T>::type base_type; + typedef const base_type& type; +}; + +template <typename R, typename T, typename P1, typename P2, typename P3, + typename P4, typename P5, typename A1, typename A2> +class MethodResultCallback_5_2 : public ResultCallback2<R, A1, A2> { + public: + typedef R (T::*MethodType)(P1, P2, P3, P4, P5, A1, A2); + MethodResultCallback_5_2(T* object, MethodType method, bool self_deleting, + P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + method_(method), + self_deleting_(self_deleting), + p1_(p1), + p2_(p2), + p3_(p3), + p4_(p4), + p5_(p5) {} + ~MethodResultCallback_5_2() {} + + R Run(A1 a1, A2 a2) { + bool needs_delete = self_deleting_; + R result = (object_->*method_)(p1_, p2_, p3_, p4_, p5_, a1, a2); + if (needs_delete) delete this; + return result; + } + + private: + T* object_; + MethodType method_; + bool self_deleting_; + typename internal_remove_reference<P1>::type p1_; + typename internal_remove_reference<P2>::type p2_; + typename internal_remove_reference<P3>::type p3_; + typename internal_remove_reference<P4>::type p4_; + typename internal_remove_reference<P5>::type p5_; +}; + } // namespace internal // See Closure. @@ -1104,6 +1262,48 @@ inline Closure* NewPermanentCallback( object, method, false, arg1, arg2); } +// See ResultCallback1 +template<typename R, typename A1> +inline ResultCallback1<R, A1>* NewCallback(R (*function)(A1)) { + return new internal::FunctionResultCallback_0_1<R, A1>(function, true); +} + +// See ResultCallback1 +template<typename R, typename A1> +inline ResultCallback1<R, A1>* NewPermanentCallback(R (*function)(A1)) { + return new internal::FunctionResultCallback_0_1<R, A1>(function, false); +} + +// See ResultCallback1 +template<typename R, typename P1, typename A1> +inline ResultCallback1<R, A1>* NewCallback(R (*function)(P1, A1), P1 p1) { + return new internal::FunctionResultCallback_1_1<R, P1, A1>( + function, true, p1); +} + +// See ResultCallback1 +template<typename R, typename P1, typename A1> +inline ResultCallback1<R, A1>* NewPermanentCallback( + R (*function)(P1, A1), P1 p1) { + return new internal::FunctionResultCallback_1_1<R, P1, A1>( + function, false, p1); +} + +// See MethodResultCallback_5_2 +template <typename R, typename T, typename P1, typename P2, typename P3, + typename P4, typename P5, typename A1, typename A2> +inline ResultCallback2<R, A1, A2>* NewPermanentCallback( + T* object, R (T::*function)(P1, P2, P3, P4, P5, A1, A2), + typename internal::InternalConstRef<P1>::type p1, + typename internal::InternalConstRef<P2>::type p2, + typename internal::InternalConstRef<P3>::type p3, + typename internal::InternalConstRef<P4>::type p4, + typename internal::InternalConstRef<P5>::type p5) { + return new internal::MethodResultCallback_5_2<R, T, P1, P2, P3, P4, P5, A1, + A2>(object, function, false, p1, + p2, p3, p4, p5); +} + // A function which does nothing. Useful for creating no-op callbacks, e.g.: // Closure* nothing = NewCallback(&DoNothing); void LIBPROTOBUF_EXPORT DoNothing(); @@ -1174,11 +1374,7 @@ 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. +#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) template<typename T> class ThreadLocalStorage { public: @@ -1228,9 +1424,114 @@ LIBPROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len); } // namespace internal // =================================================================== +// from google3/base/port.h + +// The following guarantees declaration of the byte swap functions, and +// defines __BYTE_ORDER for MSVC +#ifdef _MSC_VER +#include <stdlib.h> // NOLINT(build/include) +#define __BYTE_ORDER __LITTLE_ENDIAN +#define bswap_16(x) _byteswap_ushort(x) +#define bswap_32(x) _byteswap_ulong(x) +#define bswap_64(x) _byteswap_uint64(x) + +#elif defined(__APPLE__) +// Mac OS X / Darwin features +#include <libkern/OSByteOrder.h> +#define bswap_16(x) OSSwapInt16(x) +#define bswap_32(x) OSSwapInt32(x) +#define bswap_64(x) OSSwapInt64(x) + +#elif defined(__GLIBC__) || defined(__CYGWIN__) +#include <byteswap.h> // IWYU pragma: export + +#else + +static inline uint16 bswap_16(uint16 x) { + return static_cast<uint16>(((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)); +} +#define bswap_16(x) bswap_16(x) +static inline uint32 bswap_32(uint32 x) { + return (((x & 0xFF) << 24) | + ((x & 0xFF00) << 8) | + ((x & 0xFF0000) >> 8) | + ((x & 0xFF000000) >> 24)); +} +#define bswap_32(x) bswap_32(x) +static inline uint64 bswap_64(uint64 x) { + return (((x & GG_ULONGLONG(0xFF)) << 56) | + ((x & GG_ULONGLONG(0xFF00)) << 40) | + ((x & GG_ULONGLONG(0xFF0000)) << 24) | + ((x & GG_ULONGLONG(0xFF000000)) << 8) | + ((x & GG_ULONGLONG(0xFF00000000)) >> 8) | + ((x & GG_ULONGLONG(0xFF0000000000)) >> 24) | + ((x & GG_ULONGLONG(0xFF000000000000)) >> 40) | + ((x & GG_ULONGLONG(0xFF00000000000000)) >> 56)); +} +#define bswap_64(x) bswap_64(x) + +#endif + +// =================================================================== // from google3/util/endian/endian.h LIBPROTOBUF_EXPORT uint32 ghtonl(uint32 x); +class BigEndian { + public: +#ifdef PROTOBUF_LITTLE_ENDIAN + + static uint16 FromHost16(uint16 x) { return bswap_16(x); } + static uint16 ToHost16(uint16 x) { return bswap_16(x); } + + static uint32 FromHost32(uint32 x) { return bswap_32(x); } + static uint32 ToHost32(uint32 x) { return bswap_32(x); } + + static uint64 FromHost64(uint64 x) { return bswap_64(x); } + static uint64 ToHost64(uint64 x) { return bswap_64(x); } + + static bool IsLittleEndian() { return true; } + +#else + + static uint16 FromHost16(uint16 x) { return x; } + static uint16 ToHost16(uint16 x) { return x; } + + static uint32 FromHost32(uint32 x) { return x; } + static uint32 ToHost32(uint32 x) { return x; } + + static uint64 FromHost64(uint64 x) { return x; } + static uint64 ToHost64(uint64 x) { return x; } + + static bool IsLittleEndian() { return false; } + +#endif /* ENDIAN */ + + // Functions to do unaligned loads and stores in big-endian order. + static uint16 Load16(const void *p) { + return ToHost16(GOOGLE_UNALIGNED_LOAD16(p)); + } + + static void Store16(void *p, uint16 v) { + GOOGLE_UNALIGNED_STORE16(p, FromHost16(v)); + } + + static uint32 Load32(const void *p) { + return ToHost32(GOOGLE_UNALIGNED_LOAD32(p)); + } + + static void Store32(void *p, uint32 v) { + GOOGLE_UNALIGNED_STORE32(p, FromHost32(v)); + } + + static uint64 Load64(const void *p) { + return ToHost64(GOOGLE_UNALIGNED_LOAD64(p)); + } + + static void Store64(void *p, uint64 v) { + GOOGLE_UNALIGNED_STORE64(p, FromHost64(v)); + } +}; + // =================================================================== // Shutdown support. diff --git a/src/google/protobuf/stubs/common_unittest.cc b/src/google/protobuf/stubs/common_unittest.cc index 5f458e98..f9e2cfd4 100644 --- a/src/google/protobuf/stubs/common_unittest.cc +++ b/src/google/protobuf/stubs/common_unittest.cc @@ -39,8 +39,6 @@ #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> -#include "config.h" - namespace google { namespace protobuf { namespace { diff --git a/src/google/protobuf/stubs/mathlimits.cc b/src/google/protobuf/stubs/mathlimits.cc new file mode 100644 index 00000000..0373b2bb --- /dev/null +++ b/src/google/protobuf/stubs/mathlimits.cc @@ -0,0 +1,144 @@ +// 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. + +// All Rights Reserved. +// +// Author: Maxim Lifantsev +// + +#include <google/protobuf/stubs/mathlimits.h> + +#include <google/protobuf/stubs/common.h> + +namespace google { +namespace protobuf { + +// MSVC++ 2005 and older compilers think the header declaration was a +// definition, and erroneously flag these as a duplicate definition. +#if defined(COMPILER_MSVC) || __cpluscplus < 201103L + +#define DEF_COMMON_LIMITS(Type) +#define DEF_UNSIGNED_INT_LIMITS(Type) +#define DEF_SIGNED_INT_LIMITS(Type) +#define DEF_PRECISION_LIMITS(Type) + +#else + +#define DEF_COMMON_LIMITS(Type) \ +const bool MathLimits<Type>::kIsSigned; \ +const bool MathLimits<Type>::kIsInteger; \ +const int MathLimits<Type>::kMin10Exp; \ +const int MathLimits<Type>::kMax10Exp; + +#define DEF_UNSIGNED_INT_LIMITS(Type) \ +DEF_COMMON_LIMITS(Type) \ +const Type MathLimits<Type>::kPosMin; \ +const Type MathLimits<Type>::kPosMax; \ +const Type MathLimits<Type>::kMin; \ +const Type MathLimits<Type>::kMax; \ +const Type MathLimits<Type>::kEpsilon; \ +const Type MathLimits<Type>::kStdError; + +#define DEF_SIGNED_INT_LIMITS(Type) \ +DEF_UNSIGNED_INT_LIMITS(Type) \ +const Type MathLimits<Type>::kNegMin; \ +const Type MathLimits<Type>::kNegMax; + +#define DEF_PRECISION_LIMITS(Type) \ +const int MathLimits<Type>::kPrecisionDigits; + +#endif // not COMPILER_MSVC + +// http://en.wikipedia.org/wiki/Quadruple_precision_floating-point_format#Double-double_arithmetic +// With some compilers (gcc 4.6.x) on some platforms (powerpc64), +// "long double" is implemented as a pair of double: "double double" format. +// This causes a problem with epsilon (eps). +// eps is the smallest positive number such that 1.0 + eps > 1.0 +// +// Normal format: 1.0 + e = 1.0...01 // N-1 zeros for N fraction bits +// D-D format: 1.0 + e = 1.000...0001 // epsilon can be very small +// +// In the normal format, 1.0 + e has to fit in one stretch of bits. +// The maximum rounding error is half of eps. +// +// In the double-double format, 1.0 + e splits across two doubles: +// 1.0 in the high double, e in the low double, and they do not have to +// be contiguous. The maximum rounding error on a value close to 1.0 is +// much larger than eps. +// +// Some code checks for errors by comparing a computed value to a golden +// value +/- some multiple of the maximum rounding error. The maximum +// rounding error is not available so we use eps as an approximation +// instead. That fails when long double is in the double-double format. +// Therefore, we define kStdError as a multiple of +// max(DBL_EPSILON * DBL_EPSILON, kEpsilon) rather than a multiple of kEpsilon. + +#define DEF_FP_LIMITS(Type, PREFIX) \ +DEF_COMMON_LIMITS(Type) \ +const Type MathLimits<Type>::kPosMin = PREFIX##_MIN; \ +const Type MathLimits<Type>::kPosMax = PREFIX##_MAX; \ +const Type MathLimits<Type>::kMin = -MathLimits<Type>::kPosMax; \ +const Type MathLimits<Type>::kMax = MathLimits<Type>::kPosMax; \ +const Type MathLimits<Type>::kNegMin = -MathLimits<Type>::kPosMin; \ +const Type MathLimits<Type>::kNegMax = -MathLimits<Type>::kPosMax; \ +const Type MathLimits<Type>::kEpsilon = PREFIX##_EPSILON; \ +/* 32 is 5 bits of mantissa error; should be adequate for common errors */ \ +const Type MathLimits<Type>::kStdError = \ + 32 * (DBL_EPSILON * DBL_EPSILON > MathLimits<Type>::kEpsilon \ + ? DBL_EPSILON * DBL_EPSILON : MathLimits<Type>::kEpsilon); \ +DEF_PRECISION_LIMITS(Type) \ +const Type MathLimits<Type>::kNaN = HUGE_VAL - HUGE_VAL; \ +const Type MathLimits<Type>::kPosInf = HUGE_VAL; \ +const Type MathLimits<Type>::kNegInf = -HUGE_VAL; + +// The following are *not* casts! +DEF_SIGNED_INT_LIMITS(int8) +DEF_SIGNED_INT_LIMITS(int16) // NOLINT(readability/casting) +DEF_SIGNED_INT_LIMITS(int32) // NOLINT(readability/casting) +DEF_SIGNED_INT_LIMITS(int64) // NOLINT(readability/casting) +DEF_UNSIGNED_INT_LIMITS(uint8) +DEF_UNSIGNED_INT_LIMITS(uint16) // NOLINT(readability/casting) +DEF_UNSIGNED_INT_LIMITS(uint32) // NOLINT(readability/casting) +DEF_UNSIGNED_INT_LIMITS(uint64) // NOLINT(readability/casting) + +DEF_SIGNED_INT_LIMITS(long int) +DEF_UNSIGNED_INT_LIMITS(unsigned long int) + +DEF_FP_LIMITS(float, FLT) +DEF_FP_LIMITS(double, DBL) +DEF_FP_LIMITS(long double, LDBL); + +#undef DEF_COMMON_LIMITS +#undef DEF_SIGNED_INT_LIMITS +#undef DEF_UNSIGNED_INT_LIMITS +#undef DEF_FP_LIMITS +#undef DEF_PRECISION_LIMITS +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/mathlimits.h b/src/google/protobuf/stubs/mathlimits.h new file mode 100644 index 00000000..d9846940 --- /dev/null +++ b/src/google/protobuf/stubs/mathlimits.h @@ -0,0 +1,279 @@ +// 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. + +// All Rights Reserved. +// +// Author: Maxim Lifantsev +// +// Useful integer and floating point limits and type traits. +// +// This partially replaces/duplictes numeric_limits<> from <limits>. +// We get a Google-style class that we have a greater control over +// and thus can add new features to it or fix whatever happens to be broken in +// numeric_limits for the compilers we use. +// + +#ifndef UTIL_MATH_MATHLIMITS_H__ +#define UTIL_MATH_MATHLIMITS_H__ + +// <math.h> lacks a lot of prototypes. However, this file needs <math.h> to +// access old-fashioned isinf et al. Even worse more: this file must not +// include <cmath> because that breaks the definition of isinf with gcc 4.9. +// +// TODO(mec): after C++11 everywhere, use <cmath> and std::isinf in this file. +#include <math.h> +#include <string.h> + +#include <cfloat> + +#include <google/protobuf/stubs/common.h> + +// ========================================================================= // + +// Useful integer and floating point limits and type traits. +// This is just for the documentation; +// real members are defined in our specializations below. +namespace google { +namespace protobuf { +template<typename T> struct MathLimits { + // Type name. + typedef T Type; + // Unsigned version of the Type with the same byte size. + // Same as Type for floating point and unsigned types. + typedef T UnsignedType; + // If the type supports negative values. + static const bool kIsSigned; + // If the type supports only integer values. + static const bool kIsInteger; + // Magnitude-wise smallest representable positive value. + static const Type kPosMin; + // Magnitude-wise largest representable positive value. + static const Type kPosMax; + // Smallest representable value. + static const Type kMin; + // Largest representable value. + static const Type kMax; + // Magnitude-wise smallest representable negative value. + // Present only if kIsSigned. + static const Type kNegMin; + // Magnitude-wise largest representable negative value. + // Present only if kIsSigned. + static const Type kNegMax; + // Smallest integer x such that 10^x is representable. + static const int kMin10Exp; + // Largest integer x such that 10^x is representable. + static const int kMax10Exp; + // Smallest positive value such that Type(1) + kEpsilon != Type(1) + static const Type kEpsilon; + // Typical rounding error that is enough to cover + // a few simple floating-point operations. + // Slightly larger than kEpsilon to account for a few rounding errors. + // Is zero if kIsInteger. + static const Type kStdError; + // Number of decimal digits of mantissa precision. + // Present only if !kIsInteger. + static const int kPrecisionDigits; + // Not a number, i.e. result of 0/0. + // Present only if !kIsInteger. + static const Type kNaN; + // Positive infinity, i.e. result of 1/0. + // Present only if !kIsInteger. + static const Type kPosInf; + // Negative infinity, i.e. result of -1/0. + // Present only if !kIsInteger. + static const Type kNegInf; + + // NOTE: Special floating point values behave + // in a special (but mathematically-logical) way + // in terms of (in)equalty comparison and mathematical operations + // -- see out unittest for examples. + + // Special floating point value testers. + // Present in integer types for convenience. + static bool IsFinite(const Type x); + static bool IsNaN(const Type x); + static bool IsInf(const Type x); + static bool IsPosInf(const Type x); + static bool IsNegInf(const Type x); +}; + +// ========================================================================= // + +// All #define-s below are simply to refactor the declarations of +// MathLimits template specializations. +// They are all #undef-ined below. + +// The hoop-jumping in *_INT_(MAX|MIN) below is so that the compiler does not +// get an overflow while computing the constants. + +#define SIGNED_INT_MAX(Type) \ + (((Type(1) << (sizeof(Type)*8 - 2)) - 1) + (Type(1) << (sizeof(Type)*8 - 2))) + +#define SIGNED_INT_MIN(Type) \ + (-(Type(1) << (sizeof(Type)*8 - 2)) - (Type(1) << (sizeof(Type)*8 - 2))) + +#define UNSIGNED_INT_MAX(Type) \ + (((Type(1) << (sizeof(Type)*8 - 1)) - 1) + (Type(1) << (sizeof(Type)*8 - 1))) + +// Compile-time selected log10-related constants for integer types. +#define SIGNED_MAX_10_EXP(Type) \ + (sizeof(Type) == 1 ? 2 : ( \ + sizeof(Type) == 2 ? 4 : ( \ + sizeof(Type) == 4 ? 9 : ( \ + sizeof(Type) == 8 ? 18 : -1)))) + +#define UNSIGNED_MAX_10_EXP(Type) \ + (sizeof(Type) == 1 ? 2 : ( \ + sizeof(Type) == 2 ? 4 : ( \ + sizeof(Type) == 4 ? 9 : ( \ + sizeof(Type) == 8 ? 19 : -1)))) + +#define DECL_INT_LIMIT_FUNCS \ + static bool IsFinite(const Type /*x*/) { return true; } \ + static bool IsNaN(const Type /*x*/) { return false; } \ + static bool IsInf(const Type /*x*/) { return false; } \ + static bool IsPosInf(const Type /*x*/) { return false; } \ + static bool IsNegInf(const Type /*x*/) { return false; } + +#define DECL_SIGNED_INT_LIMITS(IntType, UnsignedIntType) \ +template<> \ +struct LIBPROTOBUF_EXPORT MathLimits<IntType> { \ + typedef IntType Type; \ + typedef UnsignedIntType UnsignedType; \ + static const bool kIsSigned = true; \ + static const bool kIsInteger = true; \ + static const Type kPosMin = 1; \ + static const Type kPosMax = SIGNED_INT_MAX(Type); \ + static const Type kMin = SIGNED_INT_MIN(Type); \ + static const Type kMax = kPosMax; \ + static const Type kNegMin = -1; \ + static const Type kNegMax = kMin; \ + static const int kMin10Exp = 0; \ + static const int kMax10Exp = SIGNED_MAX_10_EXP(Type); \ + static const Type kEpsilon = 1; \ + static const Type kStdError = 0; \ + DECL_INT_LIMIT_FUNCS \ +}; + +#define DECL_UNSIGNED_INT_LIMITS(IntType) \ +template<> \ +struct LIBPROTOBUF_EXPORT MathLimits<IntType> { \ + typedef IntType Type; \ + typedef IntType UnsignedType; \ + static const bool kIsSigned = false; \ + static const bool kIsInteger = true; \ + static const Type kPosMin = 1; \ + static const Type kPosMax = UNSIGNED_INT_MAX(Type); \ + static const Type kMin = 0; \ + static const Type kMax = kPosMax; \ + static const int kMin10Exp = 0; \ + static const int kMax10Exp = UNSIGNED_MAX_10_EXP(Type); \ + static const Type kEpsilon = 1; \ + static const Type kStdError = 0; \ + DECL_INT_LIMIT_FUNCS \ +}; + +DECL_SIGNED_INT_LIMITS(signed char, unsigned char) +DECL_SIGNED_INT_LIMITS(signed short int, unsigned short int) +DECL_SIGNED_INT_LIMITS(signed int, unsigned int) +DECL_SIGNED_INT_LIMITS(signed long int, unsigned long int) +DECL_SIGNED_INT_LIMITS(signed long long int, unsigned long long int) +DECL_UNSIGNED_INT_LIMITS(unsigned char) +DECL_UNSIGNED_INT_LIMITS(unsigned short int) +DECL_UNSIGNED_INT_LIMITS(unsigned int) +DECL_UNSIGNED_INT_LIMITS(unsigned long int) +DECL_UNSIGNED_INT_LIMITS(unsigned long long int) + +#undef DECL_SIGNED_INT_LIMITS +#undef DECL_UNSIGNED_INT_LIMITS +#undef SIGNED_INT_MAX +#undef SIGNED_INT_MIN +#undef UNSIGNED_INT_MAX +#undef SIGNED_MAX_10_EXP +#undef UNSIGNED_MAX_10_EXP +#undef DECL_INT_LIMIT_FUNCS + +// ========================================================================= // +#ifdef WIN32 // Lacks built-in isnan() and isinf() +#define DECL_FP_LIMIT_FUNCS \ + static bool IsFinite(const Type x) { return _finite(x); } \ + static bool IsNaN(const Type x) { return _isnan(x); } \ + static bool IsInf(const Type x) { return (_fpclass(x) & (_FPCLASS_NINF | _FPCLASS_PINF)) != 0; } \ + static bool IsPosInf(const Type x) { return _fpclass(x) == _FPCLASS_PINF; } \ + static bool IsNegInf(const Type x) { return _fpclass(x) == _FPCLASS_NINF; } +#else +#define DECL_FP_LIMIT_FUNCS \ + static bool IsFinite(const Type x) { return !isinf(x) && !isnan(x); } \ + static bool IsNaN(const Type x) { return isnan(x); } \ + static bool IsInf(const Type x) { return isinf(x); } \ + static bool IsPosInf(const Type x) { return isinf(x) && x > 0; } \ + static bool IsNegInf(const Type x) { return isinf(x) && x < 0; } +#endif + +// We can't put floating-point constant values in the header here because +// such constants are not considered to be primitive-type constants by gcc. +// CAVEAT: Hence, they are going to be initialized only during +// the global objects construction time. +#define DECL_FP_LIMITS(FP_Type, PREFIX) \ +template<> \ +struct LIBPROTOBUF_EXPORT MathLimits<FP_Type> { \ + typedef FP_Type Type; \ + typedef FP_Type UnsignedType; \ + static const bool kIsSigned = true; \ + static const bool kIsInteger = false; \ + static const Type kPosMin; \ + static const Type kPosMax; \ + static const Type kMin; \ + static const Type kMax; \ + static const Type kNegMin; \ + static const Type kNegMax; \ + static const int kMin10Exp = PREFIX##_MIN_10_EXP; \ + static const int kMax10Exp = PREFIX##_MAX_10_EXP; \ + static const Type kEpsilon; \ + static const Type kStdError; \ + static const int kPrecisionDigits = PREFIX##_DIG; \ + static const Type kNaN; \ + static const Type kPosInf; \ + static const Type kNegInf; \ + DECL_FP_LIMIT_FUNCS \ +}; + +DECL_FP_LIMITS(float, FLT) +DECL_FP_LIMITS(double, DBL) +DECL_FP_LIMITS(long double, LDBL) + +#undef DECL_FP_LIMITS +#undef DECL_FP_LIMIT_FUNCS + +// ========================================================================= // +} // namespace protobuf +} // namespace google + +#endif // UTIL_MATH_MATHLIMITS_H__ diff --git a/src/google/protobuf/stubs/mathutil.h b/src/google/protobuf/stubs/mathutil.h new file mode 100644 index 00000000..87ca5e91 --- /dev/null +++ b/src/google/protobuf/stubs/mathutil.h @@ -0,0 +1,149 @@ +// 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_STUBS_MATHUTIL_H_ +#define GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_ + +#include <float.h> +#include <math.h> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/mathlimits.h> + +namespace google { +namespace protobuf { +namespace internal { +template<typename T> +bool IsNan(T value) { + return false; +} +template<> +inline bool IsNan(float value) { return isnan(value); } +template<> +inline bool IsNan(double value) { return isnan(value); } + +template<typename T> +bool AlmostEquals(T a, T b) { + return a == b; +} +template<> +inline bool AlmostEquals(float a, float b) { + return fabs(a - b) < 32 * FLT_EPSILON; +} + +template<> +inline bool AlmostEquals(double a, double b) { + return fabs(a - b) < 32 * DBL_EPSILON; +} +} // namespace internal + +class MathUtil { + public: + template<typename T> + static T Sign(T value) { + if (value == T(0) || ::google::protobuf::internal::IsNan<T>(value)) { + return value; + } + return value > T(0) ? value : -value; + } + + template<typename T> + static bool AlmostEquals(T a, T b) { + return ::google::protobuf::internal::AlmostEquals(a, b); + } + + // Largest of two values. + // Works correctly for special floating point values. + // Note: 0.0 and -0.0 are not differentiated by Max (Max(0.0, -0.0) is -0.0), + // which should be OK because, although they (can) have different + // bit representation, they are observably the same when examined + // with arithmetic and (in)equality operators. + template<typename T> + static T Max(const T x, const T y) { + return MathLimits<T>::IsNaN(x) || x > y ? x : y; + } + + // Absolute value of x + // Works correctly for unsigned types and + // for special floating point values. + // Note: 0.0 and -0.0 are not differentiated by Abs (Abs(0.0) is -0.0), + // which should be OK: see the comment for Max above. + template<typename T> + static T Abs(const T x) { + return x > T(0) ? x : -x; + } + + // Absolute value of the difference between two numbers. + // Works correctly for signed types and special floating point values. + template<typename T> + static typename MathLimits<T>::UnsignedType AbsDiff(const T x, const T y) { + // Carries out arithmetic as unsigned to avoid overflow. + typedef typename MathLimits<T>::UnsignedType R; + return x > y ? R(x) - R(y) : R(y) - R(x); + } + + // If two (usually floating point) numbers are within a certain + // fraction of their magnitude or within a certain absolute margin of error. + // This is the same as the following but faster: + // WithinFraction(x, y, fraction) || WithinMargin(x, y, margin) + // E.g. WithinFraction(0.0, 1e-10, 1e-5) is false but + // WithinFractionOrMargin(0.0, 1e-10, 1e-5, 1e-5) is true. + template<typename T> + static bool WithinFractionOrMargin(const T x, const T y, + const T fraction, const T margin); +}; + +template<typename T> +bool MathUtil::WithinFractionOrMargin(const T x, const T y, + const T fraction, const T margin) { + // Not just "0 <= fraction" to fool the compiler for unsigned types. + GOOGLE_DCHECK((T(0) < fraction || T(0) == fraction) && + fraction < T(1) && + margin >= T(0)); + + // Template specialization will convert the if() condition to a constant, + // which will cause the compiler to generate code for either the "if" part + // or the "then" part. In this way we avoid a compiler warning + // about a potential integer overflow in crosstool v12 (gcc 4.3.1). + if (MathLimits<T>::kIsInteger) { + return x == y; + } else { + // IsFinite checks are to make kPosInf and kNegInf not within fraction + if (!MathLimits<T>::IsFinite(x) && !MathLimits<T>::IsFinite(y)) { + return false; + } + T relative_margin = static_cast<T>(fraction * Max(Abs(x), Abs(y))); + return AbsDiff(x, y) <= Max(margin, relative_margin); + } +} + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_ diff --git a/src/google/protobuf/stubs/pbconfig.h b/src/google/protobuf/stubs/pbconfig.h new file mode 100644 index 00000000..0f21c560 --- /dev/null +++ b/src/google/protobuf/stubs/pbconfig.h @@ -0,0 +1,142 @@ +// 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_STUBS_PBCONFIG_H__ +#define GOOGLE_PROTOBUF_STUBS_PBCONFIG_H__ + +#define GOOGLE_PROTOBUF_HAVE_HASH_MAP 1 +#define GOOGLE_PROTOBUF_HAVE_HASH_SET 1 + +// Use C++11 unordered_{map|set} if available. +#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X) +# define GOOGLE_PROTOBUF_HAS_CXX11_HASH + +// For XCode >= 4.6: the compiler is clang with libc++. +// For earlier XCode version: the compiler is gcc-4.2.1 with libstdc++. +// libc++ provides <unordered_map> and friends even in non C++11 mode, +// and it does not provide the tr1 library. Therefore the following macro +// checks against this special case. +// Note that we should not test the __APPLE_CC__ version number or the +// __clang__ macro, since the new compiler can still use -stdlib=libstdc++, in +// which case <unordered_map> is not compilable without -std=c++11 +#elif defined(__APPLE_CC__) +# if defined(_LIBCPP_VERSION) +# define GOOGLE_PROTOBUF_HAS_CXX11_HASH +# elif __GNUC__ >= 4 +# define GOOGLE_PROTOBUF_HAS_TR1 +# else +// Not tested for gcc < 4... These setting can compile under 4.2.1 though. +# define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx +# define GOOGLE_PROTOBUF_HASH_MAP_H <ext/hash_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# define GOOGLE_PROTOBUF_HASH_SET_H <ext/hash_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# endif + +// Version checks for gcc. +#elif defined(__GNUC__) +// For GCC 4.x+, use tr1::unordered_map/set; otherwise, follow the +// instructions from: +// https://gcc.gnu.org/onlinedocs/libstdc++/manual/backwards.html +# if __GNUC__ >= 4 +# define GOOGLE_PROTOBUF_HAS_TR1 +# elif __GNUC__ >= 3 +# define GOOGLE_PROTOBUF_HASH_MAP_H <backward/hash_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# define GOOGLE_PROTOBUF_HASH_SET_H <backward/hash_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# if __GNUC__ == 3 && __GNUC_MINOR__ == 0 +# define GOOGLE_PROTOBUF_HASH_NAMESPACE std // GCC 3.0 +# else +# define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx // GCC 3.1 and later +# endif +# else +# define GOOGLE_PROTOBUF_HASH_NAMESPACE +# define GOOGLE_PROTOBUF_HASH_MAP_H <hash_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# define GOOGLE_PROTOBUF_HASH_SET_H <hash_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# endif + +// Version checks for MSC. +// Apparently Microsoft decided to move hash_map *back* to the std namespace in +// MSVC 2010: +// http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx +// And.. they are moved back to stdext in MSVC 2013 (haven't checked 2012). That +// said, use unordered_map for MSVC 2010 and beyond is our safest bet. +#elif defined(_MSC_VER) +# if _MSC_VER >= 1600 // Since Visual Studio 2010 +# define GOOGLE_PROTOBUF_HAS_CXX11_HASH +# define GOOGLE_PROTOBUF_HASH_COMPARE std::hash_compare +# elif _MSC_VER >= 1500 // Since Visual Studio 2008 +# define GOOGLE_PROTOBUF_HAS_TR1 +# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare +# elif _MSC_VER >= 1310 +# define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext +# define GOOGLE_PROTOBUF_HASH_MAP_H <hash_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# define GOOGLE_PROTOBUF_HASH_SET_H <hash_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare +# else +# define GOOGLE_PROTOBUF_HASH_NAMESPACE std +# define GOOGLE_PROTOBUF_HASH_MAP_H <hash_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# define GOOGLE_PROTOBUF_HASH_SET_H <hash_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare +# endif + +// **ADD NEW COMPILERS SUPPORT HERE.** +// For other compilers, undefine the macro and fallback to use std::map, in +// google/protobuf/stubs/hash.h +#else +# undef GOOGLE_PROTOBUF_HAVE_HASH_MAP +# undef GOOGLE_PROTOBUF_HAVE_HASH_SET +#endif + +#if defined(GOOGLE_PROTOBUF_HAS_CXX11_HASH) +# define GOOGLE_PROTOBUF_HASH_NAMESPACE std +# define GOOGLE_PROTOBUF_HASH_MAP_H <unordered_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map +# define GOOGLE_PROTOBUF_HASH_SET_H <unordered_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set +#elif defined(GOOGLE_PROTOBUF_HAS_TR1) +# define GOOGLE_PROTOBUF_HASH_NAMESPACE std::tr1 +# define GOOGLE_PROTOBUF_HASH_MAP_H <tr1/unordered_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map +# define GOOGLE_PROTOBUF_HASH_SET_H <tr1/unordered_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set +#endif + +#undef GOOGLE_PROTOBUF_HAS_CXX11_HASH +#undef GOOGLE_PROTOBUF_HAS_TR1 + +#endif // GOOGLE_PROTOBUF_STUBS_PBCONFIG_H__ diff --git a/src/google/protobuf/stubs/platform_macros.h b/src/google/protobuf/stubs/platform_macros.h index 2ce7fc8f..9e0344d8 100644 --- a/src/google/protobuf/stubs/platform_macros.h +++ b/src/google/protobuf/stubs/platform_macros.h @@ -31,8 +31,6 @@ #ifndef GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ #define GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ -#include <google/protobuf/stubs/common.h> - #define GOOGLE_PROTOBUF_PLATFORM_ERROR \ #error "Host platform was not detected as supported by protobuf" @@ -111,4 +109,12 @@ GOOGLE_PROTOBUF_PLATFORM_ERROR #undef GOOGLE_PROTOBUF_PLATFORM_ERROR +#if defined(GOOGLE_PROTOBUF_OS_ANDROID) || 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. +#define GOOGLE_PROTOBUF_NO_THREADLOCAL +#endif + #endif // GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ diff --git a/src/google/protobuf/stubs/status.cc b/src/google/protobuf/stubs/status.cc new file mode 100644 index 00000000..7314c563 --- /dev/null +++ b/src/google/protobuf/stubs/status.cc @@ -0,0 +1,135 @@ +// 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/stubs/status.h> + +#include <ostream> +#include <stdint.h> +#include <stdio.h> +#include <string> +#include <utility> + +namespace google { +namespace protobuf { +namespace util { +namespace error { +inline string CodeEnumToString(error::Code code) { + switch (code) { + case OK: + return "OK"; + case CANCELLED: + return "CANCELLED"; + case UNKNOWN: + return "UNKNOWN"; + case INVALID_ARGUMENT: + return "INVALID_ARGUMENT"; + case DEADLINE_EXCEEDED: + return "DEADLINE_EXCEEDED"; + case NOT_FOUND: + return "NOT_FOUND"; + case ALREADY_EXISTS: + return "ALREADY_EXISTS"; + case PERMISSION_DENIED: + return "PERMISSION_DENIED"; + case UNAUTHENTICATED: + return "UNAUTHENTICATED"; + case RESOURCE_EXHAUSTED: + return "RESOURCE_EXHAUSTED"; + case FAILED_PRECONDITION: + return "FAILED_PRECONDITION"; + case ABORTED: + return "ABORTED"; + case OUT_OF_RANGE: + return "OUT_OF_RANGE"; + case UNIMPLEMENTED: + return "UNIMPLEMENTED"; + case INTERNAL: + return "INTERNAL"; + case UNAVAILABLE: + return "UNAVAILABLE"; + case DATA_LOSS: + return "DATA_LOSS"; + } + + // No default clause, clang will abort if a code is missing from + // above switch. + return "UNKNOWN"; +} +} // namespace error. + +const Status Status::OK = Status(); +const Status Status::CANCELLED = Status(error::CANCELLED, ""); +const Status Status::UNKNOWN = Status(error::UNKNOWN, ""); + +Status::Status() : error_code_(error::OK) { +} + +Status::Status(error::Code error_code, StringPiece error_message) + : error_code_(error_code) { + if (error_code != error::OK) { + error_message_ = error_message.ToString(); + } +} + +Status::Status(const Status& other) + : error_code_(other.error_code_), error_message_(other.error_message_) { +} + +Status& Status::operator=(const Status& other) { + error_code_ = other.error_code_; + error_message_ = other.error_message_; + return *this; +} + +bool Status::operator==(const Status& x) const { + return error_code_ == x.error_code_ && + error_message_ == x.error_message_; +} + +string Status::ToString() const { + if (error_code_ == error::OK) { + return "OK"; + } else { + if (error_message_.empty()) { + return error::CodeEnumToString(error_code_); + } else { + return error::CodeEnumToString(error_code_) + ":" + + error_message_; + } + } +} + +ostream& operator<<(ostream& os, const Status& x) { + os << x.ToString(); + return os; +} + +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/status.h b/src/google/protobuf/stubs/status.h new file mode 100644 index 00000000..614ab994 --- /dev/null +++ b/src/google/protobuf/stubs/status.h @@ -0,0 +1,116 @@ +// 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_STUBS_STATUS_H_ +#define GOOGLE_PROTOBUF_STUBS_STATUS_H_ + +#include <iosfwd> +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/stringpiece.h> + +namespace google { +namespace protobuf { +namespace util { +namespace error { +// These values must match error codes defined in google/rpc/code.proto. +enum Code { + OK = 0, + CANCELLED = 1, + UNKNOWN = 2, + INVALID_ARGUMENT = 3, + DEADLINE_EXCEEDED = 4, + NOT_FOUND = 5, + ALREADY_EXISTS = 6, + PERMISSION_DENIED = 7, + UNAUTHENTICATED = 16, + RESOURCE_EXHAUSTED = 8, + FAILED_PRECONDITION = 9, + ABORTED = 10, + OUT_OF_RANGE = 11, + UNIMPLEMENTED = 12, + INTERNAL = 13, + UNAVAILABLE = 14, + DATA_LOSS = 15, +}; +} // namespace error + +class LIBPROTOBUF_EXPORT Status { + public: + // Creates a "successful" status. + Status(); + + // Create a status in the canonical error space with the specified + // code, and error message. If "code == 0", error_message is + // ignored and a Status object identical to Status::OK is + // constructed. + Status(error::Code error_code, StringPiece error_message); + Status(const Status&); + Status& operator=(const Status& x); + ~Status() {} + + // Some pre-defined Status objects + static const Status OK; // Identical to 0-arg constructor + static const Status CANCELLED; + static const Status UNKNOWN; + + // Accessor + bool ok() const { + return error_code_ == error::OK; + } + int error_code() const { + return error_code_; + } + StringPiece error_message() const { + return error_message_; + } + + bool operator==(const Status& x) const; + bool operator!=(const Status& x) const { + return !operator==(x); + } + + // Return a combination of the error code name and message. + string ToString() const; + + private: + error::Code error_code_; + string error_message_; +}; + +// Prints a human-readable representation of 'x' to 'os'. +LIBPROTOBUF_EXPORT ostream& operator<<(ostream& os, const Status& x); + +#define EXPECT_OK(value) EXPECT_TRUE((value).ok()) + +} // namespace util +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_STUBS_STATUS_H_ diff --git a/src/google/protobuf/stubs/status_macros.h b/src/google/protobuf/stubs/status_macros.h new file mode 100644 index 00000000..743e79a7 --- /dev/null +++ b/src/google/protobuf/stubs/status_macros.h @@ -0,0 +1,89 @@ +// 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. + +// From: util/task/contrib/status_macros/status_macros.h + +#ifndef GOOGLE_PROTOBUF_STUBS_STATUS_MACROS_H_ +#define GOOGLE_PROTOBUF_STUBS_STATUS_MACROS_H_ + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/statusor.h> + +namespace google { +namespace protobuf { +namespace util { + +// Run a command that returns a util::Status. If the called code returns an +// error status, return that status up out of this method too. +// +// Example: +// RETURN_IF_ERROR(DoThings(4)); +#define RETURN_IF_ERROR(expr) \ + do { \ + /* Using _status below to avoid capture problems if expr is "status". */ \ + const ::google::protobuf::util::Status _status = (expr); \ + if (GOOGLE_PREDICT_FALSE(!_status.ok())) return _status; \ + } while (0) + +// Internal helper for concatenating macro values. +#define STATUS_MACROS_CONCAT_NAME_INNER(x, y) x##y +#define STATUS_MACROS_CONCAT_NAME(x, y) STATUS_MACROS_CONCAT_NAME_INNER(x, y) + +template<typename T> +Status DoAssignOrReturn(T& lhs, StatusOr<T> result) { + if (result.ok()) { + lhs = result.ValueOrDie(); + } + return result.status(); +} + +#define ASSIGN_OR_RETURN_IMPL(status, lhs, rexpr) \ + Status status = DoAssignOrReturn(lhs, (rexpr)); \ + if (GOOGLE_PREDICT_FALSE(!status.ok())) return status; + +// Executes an expression that returns a util::StatusOr, extracting its value +// into the variable defined by lhs (or returning on error). +// +// Example: Assigning to an existing value +// ValueType value; +// ASSIGN_OR_RETURN(value, MaybeGetValue(arg)); +// +// WARNING: ASSIGN_OR_RETURN expands into multiple statements; it cannot be used +// in a single statement (e.g. as the body of an if statement without {})! +#define ASSIGN_OR_RETURN(lhs, rexpr) \ + ASSIGN_OR_RETURN_IMPL( \ + STATUS_MACROS_CONCAT_NAME(_status_or_value, __COUNTER__), lhs, rexpr); + +} // namespace util +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_STATUS_H_ diff --git a/src/google/protobuf/stubs/status_test.cc b/src/google/protobuf/stubs/status_test.cc new file mode 100644 index 00000000..c70c33c4 --- /dev/null +++ b/src/google/protobuf/stubs/status_test.cc @@ -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. +#include <google/protobuf/stubs/status.h> + +#include <stdio.h> + +#include <google/protobuf/testing/googletest.h> +#include <gtest/gtest.h> + +namespace google { +namespace protobuf { +namespace { +TEST(Status, Empty) { + util::Status status; + EXPECT_EQ(util::error::OK, util::Status::OK.error_code()); + EXPECT_EQ("OK", util::Status::OK.ToString()); +} + +TEST(Status, GenericCodes) { + EXPECT_EQ(util::error::OK, util::Status::OK.error_code()); + EXPECT_EQ(util::error::CANCELLED, util::Status::CANCELLED.error_code()); + EXPECT_EQ(util::error::UNKNOWN, util::Status::UNKNOWN.error_code()); +} + +TEST(Status, ConstructorZero) { + util::Status status(util::error::OK, "msg"); + EXPECT_TRUE(status.ok()); + EXPECT_EQ("OK", status.ToString()); +} + +TEST(Status, CheckOK) { + util::Status status; + GOOGLE_CHECK_OK(status); + GOOGLE_CHECK_OK(status) << "Failed"; + GOOGLE_DCHECK_OK(status) << "Failed"; +} + +TEST(Status, ErrorMessage) { + util::Status status(util::error::INVALID_ARGUMENT, ""); + EXPECT_FALSE(status.ok()); + EXPECT_EQ("", status.error_message().ToString()); + EXPECT_EQ("INVALID_ARGUMENT", status.ToString()); + status = util::Status(util::error::INVALID_ARGUMENT, "msg"); + EXPECT_FALSE(status.ok()); + EXPECT_EQ("msg", status.error_message().ToString()); + EXPECT_EQ("INVALID_ARGUMENT:msg", status.ToString()); + status = util::Status(util::error::OK, "msg"); + EXPECT_TRUE(status.ok()); + EXPECT_EQ("", status.error_message().ToString()); + EXPECT_EQ("OK", status.ToString()); +} + +TEST(Status, Copy) { + util::Status a(util::error::UNKNOWN, "message"); + util::Status b(a); + ASSERT_EQ(a.ToString(), b.ToString()); +} + +TEST(Status, Assign) { + util::Status a(util::error::UNKNOWN, "message"); + util::Status b; + b = a; + ASSERT_EQ(a.ToString(), b.ToString()); +} + +TEST(Status, AssignEmpty) { + util::Status a(util::error::UNKNOWN, "message"); + util::Status b; + a = b; + ASSERT_EQ(string("OK"), a.ToString()); + ASSERT_TRUE(b.ok()); + ASSERT_TRUE(a.ok()); +} + +TEST(Status, EqualsOK) { + ASSERT_EQ(util::Status::OK, util::Status()); +} + +TEST(Status, EqualsSame) { + const util::Status a = util::Status(util::error::CANCELLED, "message"); + const util::Status b = util::Status(util::error::CANCELLED, "message"); + ASSERT_EQ(a, b); +} + +TEST(Status, EqualsCopy) { + const util::Status a = util::Status(util::error::CANCELLED, "message"); + const util::Status b = a; + ASSERT_EQ(a, b); +} + +TEST(Status, EqualsDifferentCode) { + const util::Status a = util::Status(util::error::CANCELLED, "message"); + const util::Status b = util::Status(util::error::UNKNOWN, "message"); + ASSERT_NE(a, b); +} + +TEST(Status, EqualsDifferentMessage) { + const util::Status a = util::Status(util::error::CANCELLED, "message"); + const util::Status b = util::Status(util::error::CANCELLED, "another"); + ASSERT_NE(a, b); +} +} // namespace +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/statusor.cc b/src/google/protobuf/stubs/statusor.cc new file mode 100644 index 00000000..48d1402a --- /dev/null +++ b/src/google/protobuf/stubs/statusor.cc @@ -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. + +#include <google/protobuf/stubs/statusor.h> + +namespace google { +namespace protobuf { +namespace util { +namespace internal { + +void StatusOrHelper::Crash(const Status& status) { + GOOGLE_LOG(FATAL) << "Attempting to fetch value instead of handling error " + << status.ToString(); +} + +} // namespace internal +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/statusor.h b/src/google/protobuf/stubs/statusor.h new file mode 100644 index 00000000..a9d2b374 --- /dev/null +++ b/src/google/protobuf/stubs/statusor.h @@ -0,0 +1,259 @@ +// 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. + +// StatusOr<T> is the union of a Status object and a T +// object. StatusOr models the concept of an object that is either a +// usable value, or an error Status explaining why such a value is +// not present. To this end, StatusOr<T> does not allow its Status +// value to be Status::OK. Further, StatusOr<T*> does not allow the +// contained pointer to be NULL. +// +// The primary use-case for StatusOr<T> is as the return value of a +// function which may fail. +// +// Example client usage for a StatusOr<T>, where T is not a pointer: +// +// StatusOr<float> result = DoBigCalculationThatCouldFail(); +// if (result.ok()) { +// float answer = result.ValueOrDie(); +// printf("Big calculation yielded: %f", answer); +// } else { +// LOG(ERROR) << result.status(); +// } +// +// Example client usage for a StatusOr<T*>: +// +// StatusOr<Foo*> result = FooFactory::MakeNewFoo(arg); +// if (result.ok()) { +// std::unique_ptr<Foo> foo(result.ValueOrDie()); +// foo->DoSomethingCool(); +// } else { +// LOG(ERROR) << result.status(); +// } +// +// Example client usage for a StatusOr<std::unique_ptr<T>>: +// +// StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg); +// if (result.ok()) { +// std::unique_ptr<Foo> foo = result.ConsumeValueOrDie(); +// foo->DoSomethingCool(); +// } else { +// LOG(ERROR) << result.status(); +// } +// +// Example factory implementation returning StatusOr<T*>: +// +// StatusOr<Foo*> FooFactory::MakeNewFoo(int arg) { +// if (arg <= 0) { +// return ::util::Status(::util::error::INVALID_ARGUMENT, +// "Arg must be positive"); +// } else { +// return new Foo(arg); +// } +// } +// + +#ifndef GOOGLE_PROTOBUF_STUBS_STATUSOR_H_ +#define GOOGLE_PROTOBUF_STUBS_STATUSOR_H_ + +#include <new> +#include <string> +#include <utility> + +#include <google/protobuf/stubs/status.h> + +namespace google { +namespace protobuf { +namespace util { + +template<typename T> +class StatusOr { + template<typename U> friend class StatusOr; + + public: + // Construct a new StatusOr with Status::UNKNOWN status + StatusOr(); + + // Construct a new StatusOr with the given non-ok status. After calling + // this constructor, calls to ValueOrDie() will CHECK-fail. + // + // NOTE: Not explicit - we want to use StatusOr<T> as a return + // value, so it is convenient and sensible to be able to do 'return + // Status()' when the return type is StatusOr<T>. + // + // REQUIRES: status != Status::OK. This requirement is DCHECKed. + // In optimized builds, passing Status::OK here will have the effect + // of passing PosixErrorSpace::EINVAL as a fallback. + StatusOr(const Status& status); // NOLINT + + // Construct a new StatusOr with the given value. If T is a plain pointer, + // value must not be NULL. After calling this constructor, calls to + // ValueOrDie() will succeed, and calls to status() will return OK. + // + // NOTE: Not explicit - we want to use StatusOr<T> as a return type + // so it is convenient and sensible to be able to do 'return T()' + // when when the return type is StatusOr<T>. + // + // REQUIRES: if T is a plain pointer, value != NULL. This requirement is + // DCHECKed. In optimized builds, passing a NULL pointer here will have + // the effect of passing PosixErrorSpace::EINVAL as a fallback. + StatusOr(const T& value); // NOLINT + + // Copy constructor. + StatusOr(const StatusOr& other); + + // Conversion copy constructor, T must be copy constructible from U + template<typename U> + StatusOr(const StatusOr<U>& other); + + // Assignment operator. + StatusOr& operator=(const StatusOr& other); + + // Conversion assignment operator, T must be assignable from U + template<typename U> + StatusOr& operator=(const StatusOr<U>& other); + + // Returns a reference to our status. If this contains a T, then + // returns Status::OK. + const Status& status() const; + + // Returns this->status().ok() + bool ok() const; + + // Returns a reference to our current value, or CHECK-fails if !this->ok(). + // If you need to initialize a T object from the stored value, + // ConsumeValueOrDie() may be more efficient. + const T& ValueOrDie() const; + + private: + Status status_; + T value_; +}; + +//////////////////////////////////////////////////////////////////////////////// +// Implementation details for StatusOr<T> + +namespace internal { + +class LIBPROTOBUF_EXPORT StatusOrHelper { + public: + // Move type-agnostic error handling to the .cc. + static void Crash(const util::Status& status); + + // Customized behavior for StatusOr<T> vs. StatusOr<T*> + template<typename T> + struct Specialize; +}; + +template<typename T> +struct StatusOrHelper::Specialize { + // For non-pointer T, a reference can never be NULL. + static inline bool IsValueNull(const T& t) { return false; } +}; + +template<typename T> +struct StatusOrHelper::Specialize<T*> { + static inline bool IsValueNull(const T* t) { return t == NULL; } +}; + +} // namespace internal + +template<typename T> +inline StatusOr<T>::StatusOr() + : status_(util::Status::UNKNOWN) { +} + +template<typename T> +inline StatusOr<T>::StatusOr(const Status& status) { + if (status.ok()) { + status_ = Status(error::INTERNAL, "Status::OK is not a valid argument."); + } else { + status_ = status; + } +} + +template<typename T> +inline StatusOr<T>::StatusOr(const T& value) { + if (internal::StatusOrHelper::Specialize<T>::IsValueNull(value)) { + status_ = Status(error::INTERNAL, "NULL is not a vaild argument."); + } else { + status_ = Status::OK; + value_ = value; + } +} + +template<typename T> +inline StatusOr<T>::StatusOr(const StatusOr<T>& other) + : status_(other.status_), value_(other.value_) { +} + +template<typename T> +inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<T>& other) { + status_ = other.status_; + value_ = other.value_; + return *this; +} + +template<typename T> +template<typename U> +inline StatusOr<T>::StatusOr(const StatusOr<U>& other) + : status_(other.status_), value_(other.value_) { +} + +template<typename T> +template<typename U> +inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<U>& other) { + status_ = other.status_; + value_ = other.value_; + return *this; +} + +template<typename T> +inline const Status& StatusOr<T>::status() const { + return status_; +} + +template<typename T> +inline bool StatusOr<T>::ok() const { + return status().ok(); +} + +template<typename T> +inline const T& StatusOr<T>::ValueOrDie() const { + if (!status_.ok()) { + internal::StatusOrHelper::Crash(status_); + } + return value_; +} +} // namespace util +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_STATUSOR_H_ diff --git a/src/google/protobuf/stubs/statusor_test.cc b/src/google/protobuf/stubs/statusor_test.cc new file mode 100644 index 00000000..6e2a9e55 --- /dev/null +++ b/src/google/protobuf/stubs/statusor_test.cc @@ -0,0 +1,274 @@ +// 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/stubs/statusor.h> + +#include <errno.h> +#include <memory> + +#include <google/protobuf/testing/googletest.h> +#include <gtest/gtest.h> + +namespace google { +namespace protobuf { +namespace util { +namespace { + +class Base1 { + public: + virtual ~Base1() {} + int pad; +}; + +class Base2 { + public: + virtual ~Base2() {} + int yetotherpad; +}; + +class Derived : public Base1, public Base2 { + public: + virtual ~Derived() {} + int evenmorepad; +}; + +class CopyNoAssign { + public: + explicit CopyNoAssign(int value) : foo(value) {} + CopyNoAssign(const CopyNoAssign& other) : foo(other.foo) {} + int foo; + private: + const CopyNoAssign& operator=(const CopyNoAssign&); +}; + +TEST(StatusOr, TestDefaultCtor) { + StatusOr<int> thing; + EXPECT_FALSE(thing.ok()); + EXPECT_EQ(Status::UNKNOWN, thing.status()); +} + +TEST(StatusOr, TestStatusCtor) { + StatusOr<int> thing(Status::CANCELLED); + EXPECT_FALSE(thing.ok()); + EXPECT_EQ(Status::CANCELLED, thing.status()); +} + +TEST(StatusOr, TestValueCtor) { + const int kI = 4; + StatusOr<int> thing(kI); + EXPECT_TRUE(thing.ok()); + EXPECT_EQ(kI, thing.ValueOrDie()); +} + +TEST(StatusOr, TestCopyCtorStatusOk) { + const int kI = 4; + StatusOr<int> original(kI); + StatusOr<int> copy(original); + EXPECT_EQ(original.status(), copy.status()); + EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie()); +} + +TEST(StatusOr, TestCopyCtorStatusNotOk) { + StatusOr<int> original(Status::CANCELLED); + StatusOr<int> copy(original); + EXPECT_EQ(original.status(), copy.status()); +} + +TEST(StatusOr, TestCopyCtorStatusOKConverting) { + const int kI = 4; + StatusOr<int> original(kI); + StatusOr<double> copy(original); + EXPECT_EQ(original.status(), copy.status()); + EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie()); +} + +TEST(StatusOr, TestCopyCtorStatusNotOkConverting) { + StatusOr<int> original(Status::CANCELLED); + StatusOr<double> copy(original); + EXPECT_EQ(original.status(), copy.status()); +} + +TEST(StatusOr, TestAssignmentStatusOk) { + const int kI = 4; + StatusOr<int> source(kI); + StatusOr<int> target; + target = source; + EXPECT_EQ(source.status(), target.status()); + EXPECT_EQ(source.ValueOrDie(), target.ValueOrDie()); +} + +TEST(StatusOr, TestAssignmentStatusNotOk) { + StatusOr<int> source(Status::CANCELLED); + StatusOr<int> target; + target = source; + EXPECT_EQ(source.status(), target.status()); +} + +TEST(StatusOr, TestAssignmentStatusOKConverting) { + const int kI = 4; + StatusOr<int> source(kI); + StatusOr<double> target; + target = source; + EXPECT_EQ(source.status(), target.status()); + EXPECT_DOUBLE_EQ(source.ValueOrDie(), target.ValueOrDie()); +} + +TEST(StatusOr, TestAssignmentStatusNotOkConverting) { + StatusOr<int> source(Status::CANCELLED); + StatusOr<double> target; + target = source; + EXPECT_EQ(source.status(), target.status()); +} + +TEST(StatusOr, TestStatus) { + StatusOr<int> good(4); + EXPECT_TRUE(good.ok()); + StatusOr<int> bad(Status::CANCELLED); + EXPECT_FALSE(bad.ok()); + EXPECT_EQ(Status::CANCELLED, bad.status()); +} + +TEST(StatusOr, TestValue) { + const int kI = 4; + StatusOr<int> thing(kI); + EXPECT_EQ(kI, thing.ValueOrDie()); +} + +TEST(StatusOr, TestValueConst) { + const int kI = 4; + const StatusOr<int> thing(kI); + EXPECT_EQ(kI, thing.ValueOrDie()); +} + +TEST(StatusOr, TestPointerDefaultCtor) { + StatusOr<int*> thing; + EXPECT_FALSE(thing.ok()); + EXPECT_EQ(Status::UNKNOWN, thing.status()); +} + +TEST(StatusOr, TestPointerStatusCtor) { + StatusOr<int*> thing(Status::CANCELLED); + EXPECT_FALSE(thing.ok()); + EXPECT_EQ(Status::CANCELLED, thing.status()); +} + +TEST(StatusOr, TestPointerValueCtor) { + const int kI = 4; + StatusOr<const int*> thing(&kI); + EXPECT_TRUE(thing.ok()); + EXPECT_EQ(&kI, thing.ValueOrDie()); +} + +TEST(StatusOr, TestPointerCopyCtorStatusOk) { + const int kI = 0; + StatusOr<const int*> original(&kI); + StatusOr<const int*> copy(original); + EXPECT_EQ(original.status(), copy.status()); + EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie()); +} + +TEST(StatusOr, TestPointerCopyCtorStatusNotOk) { + StatusOr<int*> original(Status::CANCELLED); + StatusOr<int*> copy(original); + EXPECT_EQ(original.status(), copy.status()); +} + +TEST(StatusOr, TestPointerCopyCtorStatusOKConverting) { + Derived derived; + StatusOr<Derived*> original(&derived); + StatusOr<Base2*> copy(original); + EXPECT_EQ(original.status(), copy.status()); + EXPECT_EQ(static_cast<const Base2*>(original.ValueOrDie()), + copy.ValueOrDie()); +} + +TEST(StatusOr, TestPointerCopyCtorStatusNotOkConverting) { + StatusOr<Derived*> original(Status::CANCELLED); + StatusOr<Base2*> copy(original); + EXPECT_EQ(original.status(), copy.status()); +} + +TEST(StatusOr, TestPointerAssignmentStatusOk) { + const int kI = 0; + StatusOr<const int*> source(&kI); + StatusOr<const int*> target; + target = source; + EXPECT_EQ(source.status(), target.status()); + EXPECT_EQ(source.ValueOrDie(), target.ValueOrDie()); +} + +TEST(StatusOr, TestPointerAssignmentStatusNotOk) { + StatusOr<int*> source(Status::CANCELLED); + StatusOr<int*> target; + target = source; + EXPECT_EQ(source.status(), target.status()); +} + +TEST(StatusOr, TestPointerAssignmentStatusOKConverting) { + Derived derived; + StatusOr<Derived*> source(&derived); + StatusOr<Base2*> target; + target = source; + EXPECT_EQ(source.status(), target.status()); + EXPECT_EQ(static_cast<const Base2*>(source.ValueOrDie()), + target.ValueOrDie()); +} + +TEST(StatusOr, TestPointerAssignmentStatusNotOkConverting) { + StatusOr<Derived*> source(Status::CANCELLED); + StatusOr<Base2*> target; + target = source; + EXPECT_EQ(source.status(), target.status()); +} + +TEST(StatusOr, TestPointerStatus) { + const int kI = 0; + StatusOr<const int*> good(&kI); + EXPECT_TRUE(good.ok()); + StatusOr<const int*> bad(Status::CANCELLED); + EXPECT_EQ(Status::CANCELLED, bad.status()); +} + +TEST(StatusOr, TestPointerValue) { + const int kI = 0; + StatusOr<const int*> thing(&kI); + EXPECT_EQ(&kI, thing.ValueOrDie()); +} + +TEST(StatusOr, TestPointerValueConst) { + const int kI = 0; + const StatusOr<const int*> thing(&kI); + EXPECT_EQ(&kI, thing.ValueOrDie()); +} + +} // namespace +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/stringpiece.cc b/src/google/protobuf/stubs/stringpiece.cc new file mode 100644 index 00000000..989474b7 --- /dev/null +++ b/src/google/protobuf/stubs/stringpiece.cc @@ -0,0 +1,268 @@ +// 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/stubs/stringpiece.h> + +#include <string.h> +#include <algorithm> +#include <climits> +#include <string> +#include <ostream> + +namespace google { +namespace protobuf { +std::ostream& operator<<(std::ostream& o, StringPiece piece) { + o.write(piece.data(), piece.size()); + return o; +} + +// Out-of-line error path. +void StringPiece::LogFatalSizeTooBig(size_t size, const char* details) { + GOOGLE_LOG(FATAL) << "size too big: " << size << " details: " << details; +} + +StringPiece::StringPiece(StringPiece x, stringpiece_ssize_type pos) + : ptr_(x.ptr_ + pos), length_(x.length_ - pos) { + GOOGLE_DCHECK_LE(0, pos); + GOOGLE_DCHECK_LE(pos, x.length_); +} + +StringPiece::StringPiece(StringPiece x, + stringpiece_ssize_type pos, + stringpiece_ssize_type len) + : ptr_(x.ptr_ + pos), length_(std::min(len, x.length_ - pos)) { + GOOGLE_DCHECK_LE(0, pos); + GOOGLE_DCHECK_LE(pos, x.length_); + GOOGLE_DCHECK_GE(len, 0); +} + +void StringPiece::CopyToString(string* target) const { + target->assign(ptr_, length_); +} + +void StringPiece::AppendToString(string* target) const { + target->append(ptr_, length_); +} + +bool StringPiece::Consume(StringPiece x) { + if (starts_with(x)) { + ptr_ += x.length_; + length_ -= x.length_; + return true; + } + return false; +} + +bool StringPiece::ConsumeFromEnd(StringPiece x) { + if (ends_with(x)) { + length_ -= x.length_; + return true; + } + return false; +} + +stringpiece_ssize_type StringPiece::copy(char* buf, + size_type n, + size_type pos) const { + stringpiece_ssize_type ret = std::min(length_ - pos, n); + memcpy(buf, ptr_ + pos, ret); + return ret; +} + +bool StringPiece::contains(StringPiece s) const { + return find(s, 0) != npos; +} + +stringpiece_ssize_type StringPiece::find(StringPiece s, size_type pos) const { + if (length_ <= 0 || pos > static_cast<size_type>(length_)) { + if (length_ == 0 && pos == 0 && s.length_ == 0) return 0; + return npos; + } + const char *result = std::search(ptr_ + pos, ptr_ + length_, + s.ptr_, s.ptr_ + s.length_); + return result == ptr_ + length_ ? npos : result - ptr_; +} + +stringpiece_ssize_type StringPiece::find(char c, size_type pos) const { + if (length_ <= 0 || pos >= static_cast<size_type>(length_)) { + return npos; + } + const char* result = static_cast<const char*>( + memchr(ptr_ + pos, c, length_ - pos)); + return result != NULL ? result - ptr_ : npos; +} + +stringpiece_ssize_type StringPiece::rfind(StringPiece s, size_type pos) const { + if (length_ < s.length_) return npos; + const size_t ulen = length_; + if (s.length_ == 0) return std::min(ulen, pos); + + const char* last = ptr_ + std::min(ulen - s.length_, pos) + s.length_; + const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_); + return result != last ? result - ptr_ : npos; +} + +// Search range is [0..pos] inclusive. If pos == npos, search everything. +stringpiece_ssize_type StringPiece::rfind(char c, size_type pos) const { + // Note: memrchr() is not available on Windows. + if (length_ <= 0) return npos; + for (stringpiece_ssize_type i = + std::min(pos, static_cast<size_type>(length_ - 1)); + i >= 0; --i) { + if (ptr_[i] == c) { + return i; + } + } + return npos; +} + +// For each character in characters_wanted, sets the index corresponding +// to the ASCII code of that character to 1 in table. This is used by +// the find_.*_of methods below to tell whether or not a character is in +// the lookup table in constant time. +// The argument `table' must be an array that is large enough to hold all +// the possible values of an unsigned char. Thus it should be be declared +// as follows: +// bool table[UCHAR_MAX + 1] +static inline void BuildLookupTable(StringPiece characters_wanted, + bool* table) { + const stringpiece_ssize_type length = characters_wanted.length(); + const char* const data = characters_wanted.data(); + for (stringpiece_ssize_type i = 0; i < length; ++i) { + table[static_cast<unsigned char>(data[i])] = true; + } +} + +stringpiece_ssize_type StringPiece::find_first_of(StringPiece s, + size_type pos) const { + if (length_ <= 0 || s.length_ <= 0) { + return npos; + } + // Avoid the cost of BuildLookupTable() for a single-character search. + if (s.length_ == 1) return find_first_of(s.ptr_[0], pos); + + bool lookup[UCHAR_MAX + 1] = { false }; + BuildLookupTable(s, lookup); + for (stringpiece_ssize_type i = pos; i < length_; ++i) { + if (lookup[static_cast<unsigned char>(ptr_[i])]) { + return i; + } + } + return npos; +} + +stringpiece_ssize_type StringPiece::find_first_not_of(StringPiece s, + size_type pos) const { + if (length_ <= 0) return npos; + if (s.length_ <= 0) return 0; + // Avoid the cost of BuildLookupTable() for a single-character search. + if (s.length_ == 1) return find_first_not_of(s.ptr_[0], pos); + + bool lookup[UCHAR_MAX + 1] = { false }; + BuildLookupTable(s, lookup); + for (stringpiece_ssize_type i = pos; i < length_; ++i) { + if (!lookup[static_cast<unsigned char>(ptr_[i])]) { + return i; + } + } + return npos; +} + +stringpiece_ssize_type StringPiece::find_first_not_of(char c, + size_type pos) const { + if (length_ <= 0) return npos; + + for (; pos < static_cast<size_type>(length_); ++pos) { + if (ptr_[pos] != c) { + return pos; + } + } + return npos; +} + +stringpiece_ssize_type StringPiece::find_last_of(StringPiece s, + size_type pos) const { + if (length_ <= 0 || s.length_ <= 0) return npos; + // Avoid the cost of BuildLookupTable() for a single-character search. + if (s.length_ == 1) return find_last_of(s.ptr_[0], pos); + + bool lookup[UCHAR_MAX + 1] = { false }; + BuildLookupTable(s, lookup); + for (stringpiece_ssize_type i = + std::min(pos, static_cast<size_type>(length_ - 1)); i >= 0; --i) { + if (lookup[static_cast<unsigned char>(ptr_[i])]) { + return i; + } + } + return npos; +} + +stringpiece_ssize_type StringPiece::find_last_not_of(StringPiece s, + size_type pos) const { + if (length_ <= 0) return npos; + + stringpiece_ssize_type i = std::min(pos, static_cast<size_type>(length_ - 1)); + if (s.length_ <= 0) return i; + + // Avoid the cost of BuildLookupTable() for a single-character search. + if (s.length_ == 1) return find_last_not_of(s.ptr_[0], pos); + + bool lookup[UCHAR_MAX + 1] = { false }; + BuildLookupTable(s, lookup); + for (; i >= 0; --i) { + if (!lookup[static_cast<unsigned char>(ptr_[i])]) { + return i; + } + } + return npos; +} + +stringpiece_ssize_type StringPiece::find_last_not_of(char c, + size_type pos) const { + if (length_ <= 0) return npos; + + for (stringpiece_ssize_type i = + std::min(pos, static_cast<size_type>(length_ - 1)); i >= 0; --i) { + if (ptr_[i] != c) { + return i; + } + } + return npos; +} + +StringPiece StringPiece::substr(size_type pos, size_type n) const { + if (pos > length_) pos = length_; + if (n > length_ - pos) n = length_ - pos; + return StringPiece(ptr_ + pos, n); +} + +const StringPiece::size_type StringPiece::npos = size_type(-1); + +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/stringpiece.h b/src/google/protobuf/stubs/stringpiece.h new file mode 100644 index 00000000..353a60d3 --- /dev/null +++ b/src/google/protobuf/stubs/stringpiece.h @@ -0,0 +1,440 @@ +// 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. + +// A StringPiece points to part or all of a string, Cord, double-quoted string +// literal, or other string-like object. A StringPiece does *not* own the +// string to which it points. A StringPiece is not null-terminated. +// +// You can use StringPiece as a function or method parameter. A StringPiece +// parameter can receive a double-quoted string literal argument, a "const +// char*" argument, a string argument, or a StringPiece argument with no data +// copying. Systematic use of StringPiece for arguments reduces data +// copies and strlen() calls. +// +// Prefer passing StringPieces by value: +// void MyFunction(StringPiece arg); +// If circumstances require, you may also pass by const reference: +// void MyFunction(const StringPiece& arg); // not preferred +// Both of these have the same lifetime semantics. Passing by value +// generates slightly smaller code. For more discussion, see the thread +// go/stringpiecebyvalue on c-users. +// +// StringPiece is also suitable for local variables if you know that +// the lifetime of the underlying object is longer than the lifetime +// of your StringPiece variable. +// +// Beware of binding a StringPiece to a temporary: +// StringPiece sp = obj.MethodReturningString(); // BAD: lifetime problem +// +// This code is okay: +// string str = obj.MethodReturningString(); // str owns its contents +// StringPiece sp(str); // GOOD, because str outlives sp +// +// StringPiece is sometimes a poor choice for a return value and usually a poor +// choice for a data member. If you do use a StringPiece this way, it is your +// responsibility to ensure that the object pointed to by the StringPiece +// outlives the StringPiece. +// +// A StringPiece may represent just part of a string; thus the name "Piece". +// For example, when splitting a string, vector<StringPiece> is a natural data +// type for the output. For another example, a Cord is a non-contiguous, +// potentially very long string-like object. The Cord class has an interface +// that iteratively provides StringPiece objects that point to the +// successive pieces of a Cord object. +// +// A StringPiece is not null-terminated. If you write code that scans a +// StringPiece, you must check its length before reading any characters. +// Common idioms that work on null-terminated strings do not work on +// StringPiece objects. +// +// There are several ways to create a null StringPiece: +// StringPiece() +// StringPiece(NULL) +// StringPiece(NULL, 0) +// For all of the above, sp.data() == NULL, sp.length() == 0, +// and sp.empty() == true. Also, if you create a StringPiece with +// a non-NULL pointer then sp.data() != NULL. Once created, +// sp.data() will stay either NULL or not-NULL, except if you call +// sp.clear() or sp.set(). +// +// Thus, you can use StringPiece(NULL) to signal an out-of-band value +// that is different from other StringPiece values. This is similar +// to the way that const char* p1 = NULL; is different from +// const char* p2 = "";. +// +// There are many ways to create an empty StringPiece: +// StringPiece() +// StringPiece(NULL) +// StringPiece(NULL, 0) +// StringPiece("") +// StringPiece("", 0) +// StringPiece("abcdef", 0) +// StringPiece("abcdef"+6, 0) +// For all of the above, sp.length() will be 0 and sp.empty() will be true. +// For some empty StringPiece values, sp.data() will be NULL. +// For some empty StringPiece values, sp.data() will not be NULL. +// +// Be careful not to confuse: null StringPiece and empty StringPiece. +// The set of empty StringPieces properly includes the set of null StringPieces. +// That is, every null StringPiece is an empty StringPiece, +// but some non-null StringPieces are empty Stringpieces too. +// +// All empty StringPiece values compare equal to each other. +// Even a null StringPieces compares equal to a non-null empty StringPiece: +// StringPiece() == StringPiece("", 0) +// StringPiece(NULL) == StringPiece("abc", 0) +// StringPiece(NULL, 0) == StringPiece("abcdef"+6, 0) +// +// Look carefully at this example: +// StringPiece("") == NULL +// True or false? TRUE, because StringPiece::operator== converts +// the right-hand side from NULL to StringPiece(NULL), +// and then compares two zero-length spans of characters. +// However, we are working to make this example produce a compile error. +// +// Suppose you want to write: +// bool TestWhat?(StringPiece sp) { return sp == NULL; } // BAD +// Do not do that. Write one of these instead: +// bool TestNull(StringPiece sp) { return sp.data() == NULL; } +// bool TestEmpty(StringPiece sp) { return sp.empty(); } +// The intent of TestWhat? is unclear. Did you mean TestNull or TestEmpty? +// Right now, TestWhat? behaves likes TestEmpty. +// We are working to make TestWhat? produce a compile error. +// TestNull is good to test for an out-of-band signal. +// TestEmpty is good to test for an empty StringPiece. +// +// Caveats (again): +// (1) The lifetime of the pointed-to string (or piece of a string) +// must be longer than the lifetime of the StringPiece. +// (2) There may or may not be a '\0' character after the end of +// StringPiece data. +// (3) A null StringPiece is empty. +// An empty StringPiece may or may not be a null StringPiece. + +#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_ +#define GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_ + +#include <assert.h> +#include <stddef.h> +#include <string.h> +#include <iosfwd> +#include <limits> +#include <string> + +#include <google/protobuf/stubs/common.h> + +namespace google { +namespace protobuf { +// StringPiece has *two* size types. +// StringPiece::size_type +// is unsigned +// is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64 +// no future changes intended +// stringpiece_ssize_type +// is signed +// is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64 +// future changes intended: http://go/64BitStringPiece +// +typedef string::difference_type stringpiece_ssize_type; + +// STRINGPIECE_CHECK_SIZE protects us from 32-bit overflows. +// TODO(mec): delete this after stringpiece_ssize_type goes 64 bit. +#if !defined(NDEBUG) +#define STRINGPIECE_CHECK_SIZE 1 +#elif defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#define STRINGPIECE_CHECK_SIZE 1 +#else +#define STRINGPIECE_CHECK_SIZE 0 +#endif + +class LIBPROTOBUF_EXPORT StringPiece { + private: + const char* ptr_; + stringpiece_ssize_type length_; + + // Prevent overflow in debug mode or fortified mode. + // sizeof(stringpiece_ssize_type) may be smaller than sizeof(size_t). + static stringpiece_ssize_type CheckedSsizeTFromSizeT(size_t size) { +#if STRINGPIECE_CHECK_SIZE > 0 +#ifdef max +#undef max +#endif + if (size > static_cast<size_t>( + std::numeric_limits<stringpiece_ssize_type>::max())) { + // Some people grep for this message in logs + // so take care if you ever change it. + LogFatalSizeTooBig(size, "size_t to int conversion"); + } +#endif + return static_cast<stringpiece_ssize_type>(size); + } + + // Out-of-line error path. + static void LogFatalSizeTooBig(size_t size, const char* details); + + public: + // We provide non-explicit singleton constructors so users can pass + // in a "const char*" or a "string" wherever a "StringPiece" is + // expected. + // + // Style guide exception granted: + // http://goto/style-guide-exception-20978288 + StringPiece() : ptr_(NULL), length_(0) {} + + StringPiece(const char* str) // NOLINT(runtime/explicit) + : ptr_(str), length_(0) { + if (str != NULL) { + length_ = CheckedSsizeTFromSizeT(strlen(str)); + } + } + + template <class Allocator> + StringPiece( // NOLINT(runtime/explicit) + const std::basic_string<char, std::char_traits<char>, Allocator>& str) + : ptr_(str.data()), length_(0) { + length_ = CheckedSsizeTFromSizeT(str.size()); + } +#if defined(HAS_GLOBAL_STRING) + template <class Allocator> + StringPiece( // NOLINT(runtime/explicit) + const basic_string<char, std::char_traits<char>, Allocator>& str) + : ptr_(str.data()), length_(0) { + length_ = CheckedSsizeTFromSizeT(str.size()); + } +#endif + + StringPiece(const char* offset, stringpiece_ssize_type len) + : ptr_(offset), length_(len) { + assert(len >= 0); + } + + // Substring of another StringPiece. + // pos must be non-negative and <= x.length(). + StringPiece(StringPiece x, stringpiece_ssize_type pos); + // Substring of another StringPiece. + // pos must be non-negative and <= x.length(). + // len must be non-negative and will be pinned to at most x.length() - pos. + StringPiece(StringPiece x, + stringpiece_ssize_type pos, + stringpiece_ssize_type len); + + // data() may return a pointer to a buffer with embedded NULs, and the + // returned buffer may or may not be null terminated. Therefore it is + // typically a mistake to pass data() to a routine that expects a NUL + // terminated string. + const char* data() const { return ptr_; } + stringpiece_ssize_type size() const { return length_; } + stringpiece_ssize_type length() const { return length_; } + bool empty() const { return length_ == 0; } + + void clear() { + ptr_ = NULL; + length_ = 0; + } + + void set(const char* data, stringpiece_ssize_type len) { + assert(len >= 0); + ptr_ = data; + length_ = len; + } + + void set(const char* str) { + ptr_ = str; + if (str != NULL) + length_ = CheckedSsizeTFromSizeT(strlen(str)); + else + length_ = 0; + } + + void set(const void* data, stringpiece_ssize_type len) { + ptr_ = reinterpret_cast<const char*>(data); + length_ = len; + } + + char operator[](stringpiece_ssize_type i) const { + assert(0 <= i); + assert(i < length_); + return ptr_[i]; + } + + void remove_prefix(stringpiece_ssize_type n) { + assert(length_ >= n); + ptr_ += n; + length_ -= n; + } + + void remove_suffix(stringpiece_ssize_type n) { + assert(length_ >= n); + length_ -= n; + } + + // returns {-1, 0, 1} + int compare(StringPiece x) const { + const stringpiece_ssize_type min_size = + length_ < x.length_ ? length_ : x.length_; + int r = memcmp(ptr_, x.ptr_, min_size); + if (r < 0) return -1; + if (r > 0) return 1; + if (length_ < x.length_) return -1; + if (length_ > x.length_) return 1; + return 0; + } + + string as_string() const { + return ToString(); + } + // We also define ToString() here, since many other string-like + // interfaces name the routine that converts to a C++ string + // "ToString", and it's confusing to have the method that does that + // for a StringPiece be called "as_string()". We also leave the + // "as_string()" method defined here for existing code. + string ToString() const { + if (ptr_ == NULL) return string(); + return string(data(), size()); + } + + operator string() const { + return ToString(); + } + + void CopyToString(string* target) const; + void AppendToString(string* target) const; + + bool starts_with(StringPiece x) const { + return (length_ >= x.length_) && (memcmp(ptr_, x.ptr_, x.length_) == 0); + } + + bool ends_with(StringPiece x) const { + return ((length_ >= x.length_) && + (memcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0)); + } + + // Checks whether StringPiece starts with x and if so advances the beginning + // of it to past the match. It's basically a shortcut for starts_with + // followed by remove_prefix. + bool Consume(StringPiece x); + // Like above but for the end of the string. + bool ConsumeFromEnd(StringPiece x); + + // standard STL container boilerplate + typedef char value_type; + typedef const char* pointer; + typedef const char& reference; + typedef const char& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + static const size_type npos; + typedef const char* const_iterator; + typedef const char* iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + iterator begin() const { return ptr_; } + iterator end() const { return ptr_ + length_; } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(ptr_ + length_); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(ptr_); + } + stringpiece_ssize_type max_size() const { return length_; } + stringpiece_ssize_type capacity() const { return length_; } + + // cpplint.py emits a false positive [build/include_what_you_use] + stringpiece_ssize_type copy(char* buf, size_type n, size_type pos = 0) const; // NOLINT + + bool contains(StringPiece s) const; + + stringpiece_ssize_type find(StringPiece s, size_type pos = 0) const; + stringpiece_ssize_type find(char c, size_type pos = 0) const; + stringpiece_ssize_type rfind(StringPiece s, size_type pos = npos) const; + stringpiece_ssize_type rfind(char c, size_type pos = npos) const; + + stringpiece_ssize_type find_first_of(StringPiece s, size_type pos = 0) const; + stringpiece_ssize_type find_first_of(char c, size_type pos = 0) const { + return find(c, pos); + } + stringpiece_ssize_type find_first_not_of(StringPiece s, + size_type pos = 0) const; + stringpiece_ssize_type find_first_not_of(char c, size_type pos = 0) const; + stringpiece_ssize_type find_last_of(StringPiece s, + size_type pos = npos) const; + stringpiece_ssize_type find_last_of(char c, size_type pos = npos) const { + return rfind(c, pos); + } + stringpiece_ssize_type find_last_not_of(StringPiece s, + size_type pos = npos) const; + stringpiece_ssize_type find_last_not_of(char c, size_type pos = npos) const; + + StringPiece substr(size_type pos, size_type n = npos) const; +}; + +// This large function is defined inline so that in a fairly common case where +// one of the arguments is a literal, the compiler can elide a lot of the +// following comparisons. +inline bool operator==(StringPiece x, StringPiece y) { + stringpiece_ssize_type len = x.size(); + if (len != y.size()) { + return false; + } + + return x.data() == y.data() || len <= 0 || + memcmp(x.data(), y.data(), len) == 0; +} + +inline bool operator!=(StringPiece x, StringPiece y) { + return !(x == y); +} + +inline bool operator<(StringPiece x, StringPiece y) { + const stringpiece_ssize_type min_size = + x.size() < y.size() ? x.size() : y.size(); + const int r = memcmp(x.data(), y.data(), min_size); + return (r < 0) || (r == 0 && x.size() < y.size()); +} + +inline bool operator>(StringPiece x, StringPiece y) { + return y < x; +} + +inline bool operator<=(StringPiece x, StringPiece y) { + return !(x > y); +} + +inline bool operator>=(StringPiece x, StringPiece y) { + return !(x < y); +} + +// allow StringPiece to be logged +extern std::ostream& operator<<(std::ostream& o, StringPiece piece); + +} // namespace protobuf +} // namespace google + +#endif // STRINGS_STRINGPIECE_H_ diff --git a/src/google/protobuf/stubs/stringpiece_unittest.cc b/src/google/protobuf/stubs/stringpiece_unittest.cc new file mode 100644 index 00000000..9b5dae13 --- /dev/null +++ b/src/google/protobuf/stubs/stringpiece_unittest.cc @@ -0,0 +1,793 @@ +// 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/stubs/stringpiece.h> + +#include <iterator> +#include <map> +#include <string> +#include <utility> +#include <vector> + +#include <google/protobuf/testing/googletest.h> +#include <gtest/gtest.h> + +namespace google { +namespace protobuf { +namespace { +TEST(StringPiece, Ctor) { + { + // Null. + StringPiece s10; + EXPECT_TRUE(s10.data() == NULL); + EXPECT_EQ(0, s10.length()); + } + + { + // const char* without length. + const char* hello = "hello"; + StringPiece s20(hello); + EXPECT_TRUE(s20.data() == hello); + EXPECT_EQ(5, s20.length()); + + // const char* with length. + StringPiece s21(hello, 4); + EXPECT_TRUE(s21.data() == hello); + EXPECT_EQ(4, s21.length()); + + // Not recommended, but valid C++ + StringPiece s22(hello, 6); + EXPECT_TRUE(s22.data() == hello); + EXPECT_EQ(6, s22.length()); + } + + { + // std::string. + std::string hola = "hola"; + StringPiece s30(hola); + EXPECT_TRUE(s30.data() == hola.data()); + EXPECT_EQ(4, s30.length()); + + // std::string with embedded '\0'. + hola.push_back('\0'); + hola.append("h2"); + hola.push_back('\0'); + StringPiece s31(hola); + EXPECT_TRUE(s31.data() == hola.data()); + EXPECT_EQ(8, s31.length()); + } + +#if defined(HAS_GLOBAL_STRING) + { + // ::string + string bonjour = "bonjour"; + StringPiece s40(bonjour); + EXPECT_TRUE(s40.data() == bonjour.data()); + EXPECT_EQ(7, s40.length()); + } +#endif + + // TODO(mec): StringPiece(StringPiece x, int pos); + // TODO(mec): StringPiece(StringPiece x, int pos, int len); + // TODO(mec): StringPiece(const StringPiece&); +} + +TEST(StringPiece, STLComparator) { + string s1("foo"); + string s2("bar"); + string s3("baz"); + + StringPiece p1(s1); + StringPiece p2(s2); + StringPiece p3(s3); + + typedef std::map<StringPiece, int> TestMap; + TestMap map; + + map.insert(std::make_pair(p1, 0)); + map.insert(std::make_pair(p2, 1)); + map.insert(std::make_pair(p3, 2)); + EXPECT_EQ(map.size(), 3); + + TestMap::const_iterator iter = map.begin(); + EXPECT_EQ(iter->second, 1); + ++iter; + EXPECT_EQ(iter->second, 2); + ++iter; + EXPECT_EQ(iter->second, 0); + ++iter; + EXPECT_TRUE(iter == map.end()); + + TestMap::iterator new_iter = map.find("zot"); + EXPECT_TRUE(new_iter == map.end()); + + new_iter = map.find("bar"); + EXPECT_TRUE(new_iter != map.end()); + + map.erase(new_iter); + EXPECT_EQ(map.size(), 2); + + iter = map.begin(); + EXPECT_EQ(iter->second, 2); + ++iter; + EXPECT_EQ(iter->second, 0); + ++iter; + EXPECT_TRUE(iter == map.end()); +} + +TEST(StringPiece, ComparisonOperators) { +#define COMPARE(result, op, x, y) \ + EXPECT_EQ(result, StringPiece((x)) op StringPiece((y))); \ + EXPECT_EQ(result, StringPiece((x)).compare(StringPiece((y))) op 0) + + COMPARE(true, ==, "", ""); + COMPARE(true, ==, "", NULL); + COMPARE(true, ==, NULL, ""); + COMPARE(true, ==, "a", "a"); + COMPARE(true, ==, "aa", "aa"); + COMPARE(false, ==, "a", ""); + COMPARE(false, ==, "", "a"); + COMPARE(false, ==, "a", "b"); + COMPARE(false, ==, "a", "aa"); + COMPARE(false, ==, "aa", "a"); + + COMPARE(false, !=, "", ""); + COMPARE(false, !=, "a", "a"); + COMPARE(false, !=, "aa", "aa"); + COMPARE(true, !=, "a", ""); + COMPARE(true, !=, "", "a"); + COMPARE(true, !=, "a", "b"); + COMPARE(true, !=, "a", "aa"); + COMPARE(true, !=, "aa", "a"); + + COMPARE(true, <, "a", "b"); + COMPARE(true, <, "a", "aa"); + COMPARE(true, <, "aa", "b"); + COMPARE(true, <, "aa", "bb"); + COMPARE(false, <, "a", "a"); + COMPARE(false, <, "b", "a"); + COMPARE(false, <, "aa", "a"); + COMPARE(false, <, "b", "aa"); + COMPARE(false, <, "bb", "aa"); + + COMPARE(true, <=, "a", "a"); + COMPARE(true, <=, "a", "b"); + COMPARE(true, <=, "a", "aa"); + COMPARE(true, <=, "aa", "b"); + COMPARE(true, <=, "aa", "bb"); + COMPARE(false, <=, "b", "a"); + COMPARE(false, <=, "aa", "a"); + COMPARE(false, <=, "b", "aa"); + COMPARE(false, <=, "bb", "aa"); + + COMPARE(false, >=, "a", "b"); + COMPARE(false, >=, "a", "aa"); + COMPARE(false, >=, "aa", "b"); + COMPARE(false, >=, "aa", "bb"); + COMPARE(true, >=, "a", "a"); + COMPARE(true, >=, "b", "a"); + COMPARE(true, >=, "aa", "a"); + COMPARE(true, >=, "b", "aa"); + COMPARE(true, >=, "bb", "aa"); + + COMPARE(false, >, "a", "a"); + COMPARE(false, >, "a", "b"); + COMPARE(false, >, "a", "aa"); + COMPARE(false, >, "aa", "b"); + COMPARE(false, >, "aa", "bb"); + COMPARE(true, >, "b", "a"); + COMPARE(true, >, "aa", "a"); + COMPARE(true, >, "b", "aa"); + COMPARE(true, >, "bb", "aa"); + + string x; + for (int i = 0; i < 256; i++) { + x += 'a'; + string y = x; + COMPARE(true, ==, x, y); + for (int j = 0; j < i; j++) { + string z = x; + z[j] = 'b'; // Differs in position 'j' + COMPARE(false, ==, x, z); + COMPARE(true, <, x, z); + COMPARE(true, >, z, x); + if (j + 1 < i) { + z[j + 1] = 'A'; // Differs in position 'j+1' as well + COMPARE(false, ==, x, z); + COMPARE(true, <, x, z); + COMPARE(true, >, z, x); + z[j + 1] = 'z'; // Differs in position 'j+1' as well + COMPARE(false, ==, x, z); + COMPARE(true, <, x, z); + COMPARE(true, >, z, x); + } + } + } + +#undef COMPARE +} + +TEST(StringPiece, STL1) { + const StringPiece a("abcdefghijklmnopqrstuvwxyz"); + const StringPiece b("abc"); + const StringPiece c("xyz"); + const StringPiece d("foobar"); + const StringPiece e; + string temp("123"); + temp += '\0'; + temp += "456"; + const StringPiece f(temp); + + EXPECT_EQ(a[6], 'g'); + EXPECT_EQ(b[0], 'a'); + EXPECT_EQ(c[2], 'z'); + EXPECT_EQ(f[3], '\0'); + EXPECT_EQ(f[5], '5'); + + EXPECT_EQ(*d.data(), 'f'); + EXPECT_EQ(d.data()[5], 'r'); + EXPECT_TRUE(e.data() == NULL); + + EXPECT_EQ(*a.begin(), 'a'); + EXPECT_EQ(*(b.begin() + 2), 'c'); + EXPECT_EQ(*(c.end() - 1), 'z'); + + EXPECT_EQ(*a.rbegin(), 'z'); + EXPECT_EQ(*(b.rbegin() + 2), 'a'); + EXPECT_EQ(*(c.rend() - 1), 'x'); + EXPECT_TRUE(a.rbegin() + 26 == a.rend()); + + EXPECT_EQ(a.size(), 26); + EXPECT_EQ(b.size(), 3); + EXPECT_EQ(c.size(), 3); + EXPECT_EQ(d.size(), 6); + EXPECT_EQ(e.size(), 0); + EXPECT_EQ(f.size(), 7); + + EXPECT_TRUE(!d.empty()); + EXPECT_TRUE(d.begin() != d.end()); + EXPECT_TRUE(d.begin() + 6 == d.end()); + + EXPECT_TRUE(e.empty()); + EXPECT_TRUE(e.begin() == e.end()); + + EXPECT_GE(a.max_size(), a.capacity()); + EXPECT_GE(a.capacity(), a.size()); + + char buf[4] = { '%', '%', '%', '%' }; + EXPECT_EQ(a.copy(buf, 4), 4); + EXPECT_EQ(buf[0], a[0]); + EXPECT_EQ(buf[1], a[1]); + EXPECT_EQ(buf[2], a[2]); + EXPECT_EQ(buf[3], a[3]); + EXPECT_EQ(a.copy(buf, 3, 7), 3); + EXPECT_EQ(buf[0], a[7]); + EXPECT_EQ(buf[1], a[8]); + EXPECT_EQ(buf[2], a[9]); + EXPECT_EQ(buf[3], a[3]); + EXPECT_EQ(c.copy(buf, 99), 3); + EXPECT_EQ(buf[0], c[0]); + EXPECT_EQ(buf[1], c[1]); + EXPECT_EQ(buf[2], c[2]); + EXPECT_EQ(buf[3], a[3]); +} + +// Separated from STL1() because some compilers produce an overly +// large stack frame for the combined function. +TEST(StringPiece, STL2) { + const StringPiece a("abcdefghijklmnopqrstuvwxyz"); + const StringPiece b("abc"); + const StringPiece c("xyz"); + StringPiece d("foobar"); + const StringPiece e; + const StringPiece f("123" "\0" "456", 7); + + d.clear(); + EXPECT_EQ(d.size(), 0); + EXPECT_TRUE(d.empty()); + EXPECT_TRUE(d.data() == NULL); + EXPECT_TRUE(d.begin() == d.end()); + + EXPECT_EQ(StringPiece::npos, string::npos); + + EXPECT_EQ(a.find(b), 0); + EXPECT_EQ(a.find(b, 1), StringPiece::npos); + EXPECT_EQ(a.find(c), 23); + EXPECT_EQ(a.find(c, 9), 23); + EXPECT_EQ(a.find(c, StringPiece::npos), StringPiece::npos); + EXPECT_EQ(b.find(c), StringPiece::npos); + EXPECT_EQ(b.find(c, StringPiece::npos), StringPiece::npos); + EXPECT_EQ(a.find(d), 0); + EXPECT_EQ(a.find(e), 0); + EXPECT_EQ(a.find(d, 12), 12); + EXPECT_EQ(a.find(e, 17), 17); + StringPiece g("xx not found bb"); + EXPECT_EQ(a.find(g), StringPiece::npos); + // empty string nonsense + EXPECT_EQ(d.find(b), StringPiece::npos); + EXPECT_EQ(e.find(b), StringPiece::npos); + EXPECT_EQ(d.find(b, 4), StringPiece::npos); + EXPECT_EQ(e.find(b, 7), StringPiece::npos); + + size_t empty_search_pos = string().find(string()); + EXPECT_EQ(d.find(d), empty_search_pos); + EXPECT_EQ(d.find(e), empty_search_pos); + EXPECT_EQ(e.find(d), empty_search_pos); + EXPECT_EQ(e.find(e), empty_search_pos); + EXPECT_EQ(d.find(d, 4), string().find(string(), 4)); + EXPECT_EQ(d.find(e, 4), string().find(string(), 4)); + EXPECT_EQ(e.find(d, 4), string().find(string(), 4)); + EXPECT_EQ(e.find(e, 4), string().find(string(), 4)); + + EXPECT_EQ(a.find('a'), 0); + EXPECT_EQ(a.find('c'), 2); + EXPECT_EQ(a.find('z'), 25); + EXPECT_EQ(a.find('$'), StringPiece::npos); + EXPECT_EQ(a.find('\0'), StringPiece::npos); + EXPECT_EQ(f.find('\0'), 3); + EXPECT_EQ(f.find('3'), 2); + EXPECT_EQ(f.find('5'), 5); + EXPECT_EQ(g.find('o'), 4); + EXPECT_EQ(g.find('o', 4), 4); + EXPECT_EQ(g.find('o', 5), 8); + EXPECT_EQ(a.find('b', 5), StringPiece::npos); + // empty string nonsense + EXPECT_EQ(d.find('\0'), StringPiece::npos); + EXPECT_EQ(e.find('\0'), StringPiece::npos); + EXPECT_EQ(d.find('\0', 4), StringPiece::npos); + EXPECT_EQ(e.find('\0', 7), StringPiece::npos); + EXPECT_EQ(d.find('x'), StringPiece::npos); + EXPECT_EQ(e.find('x'), StringPiece::npos); + EXPECT_EQ(d.find('x', 4), StringPiece::npos); + EXPECT_EQ(e.find('x', 7), StringPiece::npos); + + EXPECT_EQ(a.rfind(b), 0); + EXPECT_EQ(a.rfind(b, 1), 0); + EXPECT_EQ(a.rfind(c), 23); + EXPECT_EQ(a.rfind(c, 22), StringPiece::npos); + EXPECT_EQ(a.rfind(c, 1), StringPiece::npos); + EXPECT_EQ(a.rfind(c, 0), StringPiece::npos); + EXPECT_EQ(b.rfind(c), StringPiece::npos); + EXPECT_EQ(b.rfind(c, 0), StringPiece::npos); + EXPECT_EQ(a.rfind(d), a.as_string().rfind(string())); + EXPECT_EQ(a.rfind(e), a.as_string().rfind(string())); + EXPECT_EQ(a.rfind(d, 12), 12); + EXPECT_EQ(a.rfind(e, 17), 17); + EXPECT_EQ(a.rfind(g), StringPiece::npos); + EXPECT_EQ(d.rfind(b), StringPiece::npos); + EXPECT_EQ(e.rfind(b), StringPiece::npos); + EXPECT_EQ(d.rfind(b, 4), StringPiece::npos); + EXPECT_EQ(e.rfind(b, 7), StringPiece::npos); + // empty string nonsense + EXPECT_EQ(d.rfind(d, 4), string().rfind(string())); + EXPECT_EQ(e.rfind(d, 7), string().rfind(string())); + EXPECT_EQ(d.rfind(e, 4), string().rfind(string())); + EXPECT_EQ(e.rfind(e, 7), string().rfind(string())); + EXPECT_EQ(d.rfind(d), string().rfind(string())); + EXPECT_EQ(e.rfind(d), string().rfind(string())); + EXPECT_EQ(d.rfind(e), string().rfind(string())); + EXPECT_EQ(e.rfind(e), string().rfind(string())); + + EXPECT_EQ(g.rfind('o'), 8); + EXPECT_EQ(g.rfind('q'), StringPiece::npos); + EXPECT_EQ(g.rfind('o', 8), 8); + EXPECT_EQ(g.rfind('o', 7), 4); + EXPECT_EQ(g.rfind('o', 3), StringPiece::npos); + EXPECT_EQ(f.rfind('\0'), 3); + EXPECT_EQ(f.rfind('\0', 12), 3); + EXPECT_EQ(f.rfind('3'), 2); + EXPECT_EQ(f.rfind('5'), 5); + // empty string nonsense + EXPECT_EQ(d.rfind('o'), StringPiece::npos); + EXPECT_EQ(e.rfind('o'), StringPiece::npos); + EXPECT_EQ(d.rfind('o', 4), StringPiece::npos); + EXPECT_EQ(e.rfind('o', 7), StringPiece::npos); + + EXPECT_EQ(a.find_first_of(b), 0); + EXPECT_EQ(a.find_first_of(b, 0), 0); + EXPECT_EQ(a.find_first_of(b, 1), 1); + EXPECT_EQ(a.find_first_of(b, 2), 2); + EXPECT_EQ(a.find_first_of(b, 3), StringPiece::npos); + EXPECT_EQ(a.find_first_of(c), 23); + EXPECT_EQ(a.find_first_of(c, 23), 23); + EXPECT_EQ(a.find_first_of(c, 24), 24); + EXPECT_EQ(a.find_first_of(c, 25), 25); + EXPECT_EQ(a.find_first_of(c, 26), StringPiece::npos); + EXPECT_EQ(g.find_first_of(b), 13); + EXPECT_EQ(g.find_first_of(c), 0); + EXPECT_EQ(a.find_first_of(f), StringPiece::npos); + EXPECT_EQ(f.find_first_of(a), StringPiece::npos); + // empty string nonsense + EXPECT_EQ(a.find_first_of(d), StringPiece::npos); + EXPECT_EQ(a.find_first_of(e), StringPiece::npos); + EXPECT_EQ(d.find_first_of(b), StringPiece::npos); + EXPECT_EQ(e.find_first_of(b), StringPiece::npos); + EXPECT_EQ(d.find_first_of(d), StringPiece::npos); + EXPECT_EQ(e.find_first_of(d), StringPiece::npos); + EXPECT_EQ(d.find_first_of(e), StringPiece::npos); + EXPECT_EQ(e.find_first_of(e), StringPiece::npos); + + EXPECT_EQ(a.find_first_not_of(b), 3); + EXPECT_EQ(a.find_first_not_of(c), 0); + EXPECT_EQ(b.find_first_not_of(a), StringPiece::npos); + EXPECT_EQ(c.find_first_not_of(a), StringPiece::npos); + EXPECT_EQ(f.find_first_not_of(a), 0); + EXPECT_EQ(a.find_first_not_of(f), 0); + EXPECT_EQ(a.find_first_not_of(d), 0); + EXPECT_EQ(a.find_first_not_of(e), 0); + // empty string nonsense + EXPECT_EQ(d.find_first_not_of(a), StringPiece::npos); + EXPECT_EQ(e.find_first_not_of(a), StringPiece::npos); + EXPECT_EQ(d.find_first_not_of(d), StringPiece::npos); + EXPECT_EQ(e.find_first_not_of(d), StringPiece::npos); + EXPECT_EQ(d.find_first_not_of(e), StringPiece::npos); + EXPECT_EQ(e.find_first_not_of(e), StringPiece::npos); + + StringPiece h("===="); + EXPECT_EQ(h.find_first_not_of('='), StringPiece::npos); + EXPECT_EQ(h.find_first_not_of('=', 3), StringPiece::npos); + EXPECT_EQ(h.find_first_not_of('\0'), 0); + EXPECT_EQ(g.find_first_not_of('x'), 2); + EXPECT_EQ(f.find_first_not_of('\0'), 0); + EXPECT_EQ(f.find_first_not_of('\0', 3), 4); + EXPECT_EQ(f.find_first_not_of('\0', 2), 2); + // empty string nonsense + EXPECT_EQ(d.find_first_not_of('x'), StringPiece::npos); + EXPECT_EQ(e.find_first_not_of('x'), StringPiece::npos); + EXPECT_EQ(d.find_first_not_of('\0'), StringPiece::npos); + EXPECT_EQ(e.find_first_not_of('\0'), StringPiece::npos); + + // StringPiece g("xx not found bb"); + StringPiece i("56"); + EXPECT_EQ(h.find_last_of(a), StringPiece::npos); + EXPECT_EQ(g.find_last_of(a), g.size()-1); + EXPECT_EQ(a.find_last_of(b), 2); + EXPECT_EQ(a.find_last_of(c), a.size()-1); + EXPECT_EQ(f.find_last_of(i), 6); + EXPECT_EQ(a.find_last_of('a'), 0); + EXPECT_EQ(a.find_last_of('b'), 1); + EXPECT_EQ(a.find_last_of('z'), 25); + EXPECT_EQ(a.find_last_of('a', 5), 0); + EXPECT_EQ(a.find_last_of('b', 5), 1); + EXPECT_EQ(a.find_last_of('b', 0), StringPiece::npos); + EXPECT_EQ(a.find_last_of('z', 25), 25); + EXPECT_EQ(a.find_last_of('z', 24), StringPiece::npos); + EXPECT_EQ(f.find_last_of(i, 5), 5); + EXPECT_EQ(f.find_last_of(i, 6), 6); + EXPECT_EQ(f.find_last_of(a, 4), StringPiece::npos); + // empty string nonsense + EXPECT_EQ(f.find_last_of(d), StringPiece::npos); + EXPECT_EQ(f.find_last_of(e), StringPiece::npos); + EXPECT_EQ(f.find_last_of(d, 4), StringPiece::npos); + EXPECT_EQ(f.find_last_of(e, 4), StringPiece::npos); + EXPECT_EQ(d.find_last_of(d), StringPiece::npos); + EXPECT_EQ(d.find_last_of(e), StringPiece::npos); + EXPECT_EQ(e.find_last_of(d), StringPiece::npos); + EXPECT_EQ(e.find_last_of(e), StringPiece::npos); + EXPECT_EQ(d.find_last_of(f), StringPiece::npos); + EXPECT_EQ(e.find_last_of(f), StringPiece::npos); + EXPECT_EQ(d.find_last_of(d, 4), StringPiece::npos); + EXPECT_EQ(d.find_last_of(e, 4), StringPiece::npos); + EXPECT_EQ(e.find_last_of(d, 4), StringPiece::npos); + EXPECT_EQ(e.find_last_of(e, 4), StringPiece::npos); + EXPECT_EQ(d.find_last_of(f, 4), StringPiece::npos); + EXPECT_EQ(e.find_last_of(f, 4), StringPiece::npos); + + EXPECT_EQ(a.find_last_not_of(b), a.size()-1); + EXPECT_EQ(a.find_last_not_of(c), 22); + EXPECT_EQ(b.find_last_not_of(a), StringPiece::npos); + EXPECT_EQ(b.find_last_not_of(b), StringPiece::npos); + EXPECT_EQ(f.find_last_not_of(i), 4); + EXPECT_EQ(a.find_last_not_of(c, 24), 22); + EXPECT_EQ(a.find_last_not_of(b, 3), 3); + EXPECT_EQ(a.find_last_not_of(b, 2), StringPiece::npos); + // empty string nonsense + EXPECT_EQ(f.find_last_not_of(d), f.size()-1); + EXPECT_EQ(f.find_last_not_of(e), f.size()-1); + EXPECT_EQ(f.find_last_not_of(d, 4), 4); + EXPECT_EQ(f.find_last_not_of(e, 4), 4); + EXPECT_EQ(d.find_last_not_of(d), StringPiece::npos); + EXPECT_EQ(d.find_last_not_of(e), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of(d), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of(e), StringPiece::npos); + EXPECT_EQ(d.find_last_not_of(f), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of(f), StringPiece::npos); + EXPECT_EQ(d.find_last_not_of(d, 4), StringPiece::npos); + EXPECT_EQ(d.find_last_not_of(e, 4), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of(d, 4), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of(e, 4), StringPiece::npos); + EXPECT_EQ(d.find_last_not_of(f, 4), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of(f, 4), StringPiece::npos); + + EXPECT_EQ(h.find_last_not_of('x'), h.size() - 1); + EXPECT_EQ(h.find_last_not_of('='), StringPiece::npos); + EXPECT_EQ(b.find_last_not_of('c'), 1); + EXPECT_EQ(h.find_last_not_of('x', 2), 2); + EXPECT_EQ(h.find_last_not_of('=', 2), StringPiece::npos); + EXPECT_EQ(b.find_last_not_of('b', 1), 0); + // empty string nonsense + EXPECT_EQ(d.find_last_not_of('x'), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of('x'), StringPiece::npos); + EXPECT_EQ(d.find_last_not_of('\0'), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of('\0'), StringPiece::npos); + + EXPECT_EQ(a.substr(0, 3), b); + EXPECT_EQ(a.substr(23), c); + EXPECT_EQ(a.substr(23, 3), c); + EXPECT_EQ(a.substr(23, 99), c); + EXPECT_EQ(a.substr(0), a); + EXPECT_EQ(a.substr(3, 2), "de"); + // empty string nonsense + EXPECT_EQ(a.substr(99, 2), e); + EXPECT_EQ(d.substr(99), e); + EXPECT_EQ(d.substr(0, 99), e); + EXPECT_EQ(d.substr(99, 99), e); + // use of npos + EXPECT_EQ(a.substr(0, StringPiece::npos), a); + EXPECT_EQ(a.substr(23, StringPiece::npos), c); + EXPECT_EQ(a.substr(StringPiece::npos, 0), e); + EXPECT_EQ(a.substr(StringPiece::npos, 1), e); + EXPECT_EQ(a.substr(StringPiece::npos, StringPiece::npos), e); + + // Substring constructors. + EXPECT_EQ(StringPiece(a, 0, 3), b); + EXPECT_EQ(StringPiece(a, 23), c); + EXPECT_EQ(StringPiece(a, 23, 3), c); + EXPECT_EQ(StringPiece(a, 23, 99), c); + EXPECT_EQ(StringPiece(a, 0), a); + EXPECT_EQ(StringPiece(a, 3, 2), "de"); + // empty string nonsense + EXPECT_EQ(StringPiece(d, 0, 99), e); + // Verify that they work taking an actual string, not just a StringPiece. + string a2 = a.as_string(); + EXPECT_EQ(StringPiece(a2, 0, 3), b); + EXPECT_EQ(StringPiece(a2, 23), c); + EXPECT_EQ(StringPiece(a2, 23, 3), c); + EXPECT_EQ(StringPiece(a2, 23, 99), c); + EXPECT_EQ(StringPiece(a2, 0), a); + EXPECT_EQ(StringPiece(a2, 3, 2), "de"); +} + +TEST(StringPiece, Custom) { + StringPiece a("foobar"); + string s1("123"); + s1 += '\0'; + s1 += "456"; + StringPiece b(s1); + StringPiece e; + string s2; + + // CopyToString + a.CopyToString(&s2); + EXPECT_EQ(s2.size(), 6); + EXPECT_EQ(s2, "foobar"); + b.CopyToString(&s2); + EXPECT_EQ(s2.size(), 7); + EXPECT_EQ(s1, s2); + e.CopyToString(&s2); + EXPECT_TRUE(s2.empty()); + + // AppendToString + s2.erase(); + a.AppendToString(&s2); + EXPECT_EQ(s2.size(), 6); + EXPECT_EQ(s2, "foobar"); + a.AppendToString(&s2); + EXPECT_EQ(s2.size(), 12); + EXPECT_EQ(s2, "foobarfoobar"); + + // starts_with + EXPECT_TRUE(a.starts_with(a)); + EXPECT_TRUE(a.starts_with("foo")); + EXPECT_TRUE(a.starts_with(e)); + EXPECT_TRUE(b.starts_with(s1)); + EXPECT_TRUE(b.starts_with(b)); + EXPECT_TRUE(b.starts_with(e)); + EXPECT_TRUE(e.starts_with("")); + EXPECT_TRUE(!a.starts_with(b)); + EXPECT_TRUE(!b.starts_with(a)); + EXPECT_TRUE(!e.starts_with(a)); + + // ends with + EXPECT_TRUE(a.ends_with(a)); + EXPECT_TRUE(a.ends_with("bar")); + EXPECT_TRUE(a.ends_with(e)); + EXPECT_TRUE(b.ends_with(s1)); + EXPECT_TRUE(b.ends_with(b)); + EXPECT_TRUE(b.ends_with(e)); + EXPECT_TRUE(e.ends_with("")); + EXPECT_TRUE(!a.ends_with(b)); + EXPECT_TRUE(!b.ends_with(a)); + EXPECT_TRUE(!e.ends_with(a)); + + // remove_prefix + StringPiece c(a); + c.remove_prefix(3); + EXPECT_EQ(c, "bar"); + c = a; + c.remove_prefix(0); + EXPECT_EQ(c, a); + c.remove_prefix(c.size()); + EXPECT_EQ(c, e); + + // remove_suffix + c = a; + c.remove_suffix(3); + EXPECT_EQ(c, "foo"); + c = a; + c.remove_suffix(0); + EXPECT_EQ(c, a); + c.remove_suffix(c.size()); + EXPECT_EQ(c, e); + + // set + c.set("foobar", 6); + EXPECT_EQ(c, a); + c.set("foobar", 0); + EXPECT_EQ(c, e); + c.set("foobar", 7); + EXPECT_NE(c, a); + + c.set("foobar"); + EXPECT_EQ(c, a); + + c.set(static_cast<const void*>("foobar"), 6); + EXPECT_EQ(c, a); + c.set(static_cast<const void*>("foobar"), 0); + EXPECT_EQ(c, e); + c.set(static_cast<const void*>("foobar"), 7); + EXPECT_NE(c, a); + + // as_string + string s3(a.as_string().c_str(), 7); + EXPECT_EQ(c, s3); + string s4(e.as_string()); + EXPECT_TRUE(s4.empty()); + + // ToString + { + string s5(a.ToString().c_str(), 7); + EXPECT_EQ(c, s5); + string s6(e.ToString()); + EXPECT_TRUE(s6.empty()); + } + + // Consume + a.set("foobar"); + EXPECT_TRUE(a.Consume("foo")); + EXPECT_EQ(a, "bar"); + EXPECT_FALSE(a.Consume("foo")); + EXPECT_FALSE(a.Consume("barbar")); + EXPECT_FALSE(a.Consume("ar")); + EXPECT_EQ(a, "bar"); + + a.set("foobar"); + EXPECT_TRUE(a.ConsumeFromEnd("bar")); + EXPECT_EQ(a, "foo"); + EXPECT_FALSE(a.ConsumeFromEnd("bar")); + EXPECT_FALSE(a.ConsumeFromEnd("foofoo")); + EXPECT_FALSE(a.ConsumeFromEnd("fo")); + EXPECT_EQ(a, "foo"); +} + +TEST(StringPiece, Contains) { + StringPiece a("abcdefg"); + StringPiece b("abcd"); + StringPiece c("efg"); + StringPiece d("gh"); + EXPECT_TRUE(a.contains(b)); + EXPECT_TRUE(a.contains(c)); + EXPECT_TRUE(!a.contains(d)); +} + +TEST(StringPiece, NULLInput) { + // we used to crash here, but now we don't. + StringPiece s(NULL); + EXPECT_EQ(s.data(), (const char*)NULL); + EXPECT_EQ(s.size(), 0); + + s.set(NULL); + EXPECT_EQ(s.data(), (const char*)NULL); + EXPECT_EQ(s.size(), 0); + + // .ToString() on a StringPiece with NULL should produce the empty string. + EXPECT_EQ("", s.ToString()); + EXPECT_EQ("", s.as_string()); +} + +TEST(StringPiece, Comparisons2) { + StringPiece abc("abcdefghijklmnopqrstuvwxyz"); + + // check comparison operations on strings longer than 4 bytes. + EXPECT_EQ(abc, StringPiece("abcdefghijklmnopqrstuvwxyz")); + EXPECT_EQ(abc.compare(StringPiece("abcdefghijklmnopqrstuvwxyz")), 0); + + EXPECT_LT(abc, StringPiece("abcdefghijklmnopqrstuvwxzz")); + EXPECT_LT(abc.compare(StringPiece("abcdefghijklmnopqrstuvwxzz")), 0); + + EXPECT_GT(abc, StringPiece("abcdefghijklmnopqrstuvwxyy")); + EXPECT_GT(abc.compare(StringPiece("abcdefghijklmnopqrstuvwxyy")), 0); + + // starts_with + EXPECT_TRUE(abc.starts_with(abc)); + EXPECT_TRUE(abc.starts_with("abcdefghijklm")); + EXPECT_TRUE(!abc.starts_with("abcdefguvwxyz")); + + // ends_with + EXPECT_TRUE(abc.ends_with(abc)); + EXPECT_TRUE(!abc.ends_with("abcdefguvwxyz")); + EXPECT_TRUE(abc.ends_with("nopqrstuvwxyz")); +} + +TEST(ComparisonOpsTest, StringCompareNotAmbiguous) { + EXPECT_EQ("hello", string("hello")); + EXPECT_LT("hello", string("world")); +} + +TEST(ComparisonOpsTest, HeterogenousStringPieceEquals) { + EXPECT_EQ(StringPiece("hello"), string("hello")); + EXPECT_EQ("hello", StringPiece("hello")); +} + +TEST(FindOneCharTest, EdgeCases) { + StringPiece a("xxyyyxx"); + + // Set a = "xyyyx". + a.remove_prefix(1); + a.remove_suffix(1); + + EXPECT_EQ(0, a.find('x')); + EXPECT_EQ(0, a.find('x', 0)); + EXPECT_EQ(4, a.find('x', 1)); + EXPECT_EQ(4, a.find('x', 4)); + EXPECT_EQ(StringPiece::npos, a.find('x', 5)); + + EXPECT_EQ(4, a.rfind('x')); + EXPECT_EQ(4, a.rfind('x', 5)); + EXPECT_EQ(4, a.rfind('x', 4)); + EXPECT_EQ(0, a.rfind('x', 3)); + EXPECT_EQ(0, a.rfind('x', 0)); + + // Set a = "yyy". + a.remove_prefix(1); + a.remove_suffix(1); + + EXPECT_EQ(StringPiece::npos, a.find('x')); + EXPECT_EQ(StringPiece::npos, a.rfind('x')); +} + +#ifndef NDEBUG +TEST(NonNegativeLenTest, NonNegativeLen) { + EXPECT_DEATH(StringPiece("xyz", -1), "len >= 0"); +} +#endif // ndef DEBUG + +} // namespace +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc index 7ecc17ee..99e8bf1d 100644 --- a/src/google/protobuf/stubs/strutil.cc +++ b/src/google/protobuf/stubs/strutil.cc @@ -31,6 +31,7 @@ // from google3/strings/strutil.cc #include <google/protobuf/stubs/strutil.h> + #include <errno.h> #include <float.h> // FLT_DIG and DBL_DIG #include <limits> @@ -38,6 +39,8 @@ #include <stdio.h> #include <iterator> +#include <google/protobuf/stubs/stl_util.h> + #ifdef _WIN32 // MSVC has only _snprintf, not snprintf. // @@ -309,17 +312,6 @@ void JoinStrings(const vector<string>& components, #define IS_OCTAL_DIGIT(c) (((c) >= '0') && ((c) <= '7')) -inline int hex_digit_to_int(char c) { - /* Assume ASCII. */ - assert('0' == 0x30 && 'A' == 0x41 && 'a' == 0x61); - assert(isxdigit(c)); - int x = static_cast<unsigned char>(c); - if (x > '9') { - x += 9; - } - return x & 0xf; -} - // Protocol buffers doesn't ever care about errors, but I don't want to remove // the code. #define LOG_STRING(LEVEL, VECTOR) GOOGLE_LOG_IF(LEVEL, false) @@ -652,14 +644,15 @@ inline bool safe_parse_sign(string* text /*inout*/, return true; } -inline bool safe_parse_positive_int( - string text, int32* value_p) { +template<typename IntType> +bool safe_parse_positive_int( + string text, IntType* value_p) { int base = 10; - int32 value = 0; - const int32 vmax = std::numeric_limits<int32>::max(); + IntType value = 0; + const IntType vmax = std::numeric_limits<IntType>::max(); assert(vmax > 0); assert(vmax >= base); - const int32 vmax_over_base = vmax / base; + const IntType vmax_over_base = vmax / base; const char* start = text.data(); const char* end = start + text.size(); // loop over digits @@ -685,14 +678,15 @@ inline bool safe_parse_positive_int( return true; } -inline bool safe_parse_negative_int( - string text, int32* value_p) { +template<typename IntType> +bool safe_parse_negative_int( + const string& text, IntType* value_p) { int base = 10; - int32 value = 0; - const int32 vmin = std::numeric_limits<int32>::min(); + IntType value = 0; + const IntType vmin = std::numeric_limits<IntType>::min(); assert(vmin < 0); assert(vmin <= 0 - base); - int32 vmin_over_base = vmin / base; + IntType vmin_over_base = vmin / base; // 2003 c++ standard [expr.mul] // "... the sign of the remainder is implementation-defined." // Although (vmin/base)*base + vmin%base is always vmin. @@ -725,7 +719,8 @@ inline bool safe_parse_negative_int( return true; } -bool safe_int(string text, int32* value_p) { +template<typename IntType> +bool safe_int_internal(string text, IntType* value_p) { *value_p = 0; bool negative; if (!safe_parse_sign(&text, &negative)) { @@ -738,6 +733,16 @@ bool safe_int(string text, int32* value_p) { } } +template<typename IntType> +bool safe_uint_internal(string text, IntType* value_p) { + *value_p = 0; + bool negative; + if (!safe_parse_sign(&text, &negative) || negative) { + return false; + } + return safe_parse_positive_int(text, value_p); +} + // ---------------------------------------------------------------------- // FastIntToBuffer() // FastInt64ToBuffer() @@ -1236,6 +1241,41 @@ char* DoubleToBuffer(double value, char* buffer) { return buffer; } +static int memcasecmp(const char *s1, const char *s2, size_t len) { + const unsigned char *us1 = reinterpret_cast<const unsigned char *>(s1); + const unsigned char *us2 = reinterpret_cast<const unsigned char *>(s2); + + for ( int i = 0; i < len; i++ ) { + const int diff = + static_cast<int>(static_cast<unsigned char>(ascii_tolower(us1[i]))) - + static_cast<int>(static_cast<unsigned char>(ascii_tolower(us2[i]))); + if (diff != 0) return diff; + } + return 0; +} + +inline bool CaseEqual(StringPiece s1, StringPiece s2) { + if (s1.size() != s2.size()) return false; + return memcasecmp(s1.data(), s2.data(), s1.size()) == 0; +} + +bool safe_strtob(StringPiece str, bool* value) { + GOOGLE_CHECK(value != NULL) << "NULL output boolean given."; + if (CaseEqual(str, "true") || CaseEqual(str, "t") || + CaseEqual(str, "yes") || CaseEqual(str, "y") || + CaseEqual(str, "1")) { + *value = true; + return true; + } + if (CaseEqual(str, "false") || CaseEqual(str, "f") || + CaseEqual(str, "no") || CaseEqual(str, "n") || + CaseEqual(str, "0")) { + *value = false; + return true; + } + return false; +} + bool safe_strtof(const char* str, float* value) { char* endptr; errno = 0; // errno only gets set on errors @@ -1247,6 +1287,34 @@ bool safe_strtof(const char* str, float* value) { return *str != 0 && *endptr == 0 && errno == 0; } +bool safe_strtod(const char* str, double* value) { + char* endptr; + *value = strtod(str, &endptr); + if (endptr != str) { + while (ascii_isspace(*endptr)) ++endptr; + } + // Ignore range errors from strtod. The values it + // returns on underflow and overflow are the right + // fallback in a robust setting. + return *str != '\0' && *endptr == '\0'; +} + +bool safe_strto32(const string& str, int32* value) { + return safe_int_internal(str, value); +} + +bool safe_strtou32(const string& str, uint32* value) { + return safe_uint_internal(str, value); +} + +bool safe_strto64(const string& str, int64* value) { + return safe_int_internal(str, value); +} + +bool safe_strtou64(const string& str, uint64* value) { + return safe_uint_internal(str, value); +} + char* FloatToBuffer(float value, char* buffer) { // FLT_DIG is 6 for IEEE-754 floats, which are used on almost all // platforms these days. Just in case some system exists where FLT_DIG @@ -1518,5 +1586,661 @@ int GlobalReplaceSubstring(const string& substring, return num_replacements; } +int CalculateBase64EscapedLen(int input_len, bool do_padding) { + // Base64 encodes three bytes of input at a time. If the input is not + // divisible by three, we pad as appropriate. + // + // (from http://tools.ietf.org/html/rfc3548) + // Special processing is performed if fewer than 24 bits are available + // at the end of the data being encoded. A full encoding quantum is + // always completed at the end of a quantity. When fewer than 24 input + // bits are available in an input group, zero bits are added (on the + // right) to form an integral number of 6-bit groups. Padding at the + // end of the data is performed using the '=' character. Since all base + // 64 input is an integral number of octets, only the following cases + // can arise: + + + // Base64 encodes each three bytes of input into four bytes of output. + int len = (input_len / 3) * 4; + + if (input_len % 3 == 0) { + // (from http://tools.ietf.org/html/rfc3548) + // (1) the final quantum of encoding input is an integral multiple of 24 + // bits; here, the final unit of encoded output will be an integral + // multiple of 4 characters with no "=" padding, + } else if (input_len % 3 == 1) { + // (from http://tools.ietf.org/html/rfc3548) + // (2) the final quantum of encoding input is exactly 8 bits; here, the + // final unit of encoded output will be two characters followed by two + // "=" padding characters, or + len += 2; + if (do_padding) { + len += 2; + } + } else { // (input_len % 3 == 2) + // (from http://tools.ietf.org/html/rfc3548) + // (3) the final quantum of encoding input is exactly 16 bits; here, the + // final unit of encoded output will be three characters followed by one + // "=" padding character. + len += 3; + if (do_padding) { + len += 1; + } + } + + assert(len >= input_len); // make sure we didn't overflow + return len; +} + +// Base64Escape does padding, so this calculation includes padding. +int CalculateBase64EscapedLen(int input_len) { + return CalculateBase64EscapedLen(input_len, true); +} + +// ---------------------------------------------------------------------- +// int Base64Unescape() - base64 decoder +// int Base64Escape() - base64 encoder +// int WebSafeBase64Unescape() - Google's variation of base64 decoder +// int WebSafeBase64Escape() - Google's variation of base64 encoder +// +// Check out +// http://tools.ietf.org/html/rfc2045 for formal description, but what we +// care about is that... +// Take the encoded stuff in groups of 4 characters and turn each +// character into a code 0 to 63 thus: +// A-Z map to 0 to 25 +// a-z map to 26 to 51 +// 0-9 map to 52 to 61 +// +(- for WebSafe) maps to 62 +// /(_ for WebSafe) maps to 63 +// There will be four numbers, all less than 64 which can be represented +// by a 6 digit binary number (aaaaaa, bbbbbb, cccccc, dddddd respectively). +// Arrange the 6 digit binary numbers into three bytes as such: +// aaaaaabb bbbbcccc ccdddddd +// Equals signs (one or two) are used at the end of the encoded block to +// indicate that the text was not an integer multiple of three bytes long. +// ---------------------------------------------------------------------- + +int Base64UnescapeInternal(const char *src_param, int szsrc, + char *dest, int szdest, + const signed char* unbase64) { + static const char kPad64Equals = '='; + static const char kPad64Dot = '.'; + + int decode = 0; + int destidx = 0; + int state = 0; + unsigned int ch = 0; + unsigned int temp = 0; + + // If "char" is signed by default, using *src as an array index results in + // accessing negative array elements. Treat the input as a pointer to + // unsigned char to avoid this. + const unsigned char *src = reinterpret_cast<const unsigned char*>(src_param); + + // The GET_INPUT macro gets the next input character, skipping + // over any whitespace, and stopping when we reach the end of the + // string or when we read any non-data character. The arguments are + // an arbitrary identifier (used as a label for goto) and the number + // of data bytes that must remain in the input to avoid aborting the + // loop. +#define GET_INPUT(label, remain) \ + label: \ + --szsrc; \ + ch = *src++; \ + decode = unbase64[ch]; \ + if (decode < 0) { \ + if (ascii_isspace(ch) && szsrc >= remain) \ + goto label; \ + state = 4 - remain; \ + break; \ + } + + // if dest is null, we're just checking to see if it's legal input + // rather than producing output. (I suspect this could just be done + // with a regexp...). We duplicate the loop so this test can be + // outside it instead of in every iteration. + + if (dest) { + // This loop consumes 4 input bytes and produces 3 output bytes + // per iteration. We can't know at the start that there is enough + // data left in the string for a full iteration, so the loop may + // break out in the middle; if so 'state' will be set to the + // number of input bytes read. + + while (szsrc >= 4) { + // We'll start by optimistically assuming that the next four + // bytes of the string (src[0..3]) are four good data bytes + // (that is, no nulls, whitespace, padding chars, or illegal + // chars). We need to test src[0..2] for nulls individually + // before constructing temp to preserve the property that we + // never read past a null in the string (no matter how long + // szsrc claims the string is). + + if (!src[0] || !src[1] || !src[2] || + (temp = ((unsigned(unbase64[src[0]]) << 18) | + (unsigned(unbase64[src[1]]) << 12) | + (unsigned(unbase64[src[2]]) << 6) | + (unsigned(unbase64[src[3]])))) & 0x80000000) { + // Iff any of those four characters was bad (null, illegal, + // whitespace, padding), then temp's high bit will be set + // (because unbase64[] is -1 for all bad characters). + // + // We'll back up and resort to the slower decoder, which knows + // how to handle those cases. + + GET_INPUT(first, 4); + temp = decode; + GET_INPUT(second, 3); + temp = (temp << 6) | decode; + GET_INPUT(third, 2); + temp = (temp << 6) | decode; + GET_INPUT(fourth, 1); + temp = (temp << 6) | decode; + } else { + // We really did have four good data bytes, so advance four + // characters in the string. + + szsrc -= 4; + src += 4; + decode = -1; + ch = '\0'; + } + + // temp has 24 bits of input, so write that out as three bytes. + + if (destidx+3 > szdest) return -1; + dest[destidx+2] = temp; + temp >>= 8; + dest[destidx+1] = temp; + temp >>= 8; + dest[destidx] = temp; + destidx += 3; + } + } else { + while (szsrc >= 4) { + if (!src[0] || !src[1] || !src[2] || + (temp = ((unsigned(unbase64[src[0]]) << 18) | + (unsigned(unbase64[src[1]]) << 12) | + (unsigned(unbase64[src[2]]) << 6) | + (unsigned(unbase64[src[3]])))) & 0x80000000) { + GET_INPUT(first_no_dest, 4); + GET_INPUT(second_no_dest, 3); + GET_INPUT(third_no_dest, 2); + GET_INPUT(fourth_no_dest, 1); + } else { + szsrc -= 4; + src += 4; + decode = -1; + ch = '\0'; + } + destidx += 3; + } + } + +#undef GET_INPUT + + // if the loop terminated because we read a bad character, return + // now. + if (decode < 0 && ch != '\0' && + ch != kPad64Equals && ch != kPad64Dot && !ascii_isspace(ch)) + return -1; + + if (ch == kPad64Equals || ch == kPad64Dot) { + // if we stopped by hitting an '=' or '.', un-read that character -- we'll + // look at it again when we count to check for the proper number of + // equals signs at the end. + ++szsrc; + --src; + } else { + // This loop consumes 1 input byte per iteration. It's used to + // clean up the 0-3 input bytes remaining when the first, faster + // loop finishes. 'temp' contains the data from 'state' input + // characters read by the first loop. + while (szsrc > 0) { + --szsrc; + ch = *src++; + decode = unbase64[ch]; + if (decode < 0) { + if (ascii_isspace(ch)) { + continue; + } else if (ch == '\0') { + break; + } else if (ch == kPad64Equals || ch == kPad64Dot) { + // back up one character; we'll read it again when we check + // for the correct number of pad characters at the end. + ++szsrc; + --src; + break; + } else { + return -1; + } + } + + // Each input character gives us six bits of output. + temp = (temp << 6) | decode; + ++state; + if (state == 4) { + // If we've accumulated 24 bits of output, write that out as + // three bytes. + if (dest) { + if (destidx+3 > szdest) return -1; + dest[destidx+2] = temp; + temp >>= 8; + dest[destidx+1] = temp; + temp >>= 8; + dest[destidx] = temp; + } + destidx += 3; + state = 0; + temp = 0; + } + } + } + + // Process the leftover data contained in 'temp' at the end of the input. + int expected_equals = 0; + switch (state) { + case 0: + // Nothing left over; output is a multiple of 3 bytes. + break; + + case 1: + // Bad input; we have 6 bits left over. + return -1; + + case 2: + // Produce one more output byte from the 12 input bits we have left. + if (dest) { + if (destidx+1 > szdest) return -1; + temp >>= 4; + dest[destidx] = temp; + } + ++destidx; + expected_equals = 2; + break; + + case 3: + // Produce two more output bytes from the 18 input bits we have left. + if (dest) { + if (destidx+2 > szdest) return -1; + temp >>= 2; + dest[destidx+1] = temp; + temp >>= 8; + dest[destidx] = temp; + } + destidx += 2; + expected_equals = 1; + break; + + default: + // state should have no other values at this point. + GOOGLE_LOG(FATAL) << "This can't happen; base64 decoder state = " << state; + } + + // The remainder of the string should be all whitespace, mixed with + // exactly 0 equals signs, or exactly 'expected_equals' equals + // signs. (Always accepting 0 equals signs is a google extension + // not covered in the RFC, as is accepting dot as the pad character.) + + int equals = 0; + while (szsrc > 0 && *src) { + if (*src == kPad64Equals || *src == kPad64Dot) + ++equals; + else if (!ascii_isspace(*src)) + return -1; + --szsrc; + ++src; + } + + return (equals == 0 || equals == expected_equals) ? destidx : -1; +} + +// The arrays below were generated by the following code +// #include <sys/time.h> +// #include <stdlib.h> +// #include <string.h> +// main() +// { +// static const char Base64[] = +// "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +// char *pos; +// int idx, i, j; +// printf(" "); +// for (i = 0; i < 255; i += 8) { +// for (j = i; j < i + 8; j++) { +// pos = strchr(Base64, j); +// if ((pos == NULL) || (j == 0)) +// idx = -1; +// else +// idx = pos - Base64; +// if (idx == -1) +// printf(" %2d, ", idx); +// else +// printf(" %2d/*%c*/,", idx, j); +// } +// printf("\n "); +// } +// } +// +// where the value of "Base64[]" was replaced by one of the base-64 conversion +// tables from the functions below. +static const signed char kUnBase64[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 62/*+*/, -1, -1, -1, 63/*/ */, + 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/, + 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1, + -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, + 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, + 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/, + 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, -1, + -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/, + 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/, + 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/, + 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 +}; +static const signed char kUnWebSafeBase64[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 62/*-*/, -1, -1, + 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/, + 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1, + -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, + 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, + 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/, + 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, 63/*_*/, + -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/, + 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/, + 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/, + 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 +}; + +int WebSafeBase64Unescape(const char *src, int szsrc, char *dest, int szdest) { + return Base64UnescapeInternal(src, szsrc, dest, szdest, kUnWebSafeBase64); +} + +static bool Base64UnescapeInternal(const char* src, int slen, string* dest, + const signed char* unbase64) { + // Determine the size of the output string. Base64 encodes every 3 bytes into + // 4 characters. any leftover chars are added directly for good measure. + // This is documented in the base64 RFC: http://tools.ietf.org/html/rfc3548 + const int dest_len = 3 * (slen / 4) + (slen % 4); + + dest->resize(dest_len); + + // We are getting the destination buffer by getting the beginning of the + // string and converting it into a char *. + const int len = Base64UnescapeInternal(src, slen, string_as_array(dest), + dest_len, unbase64); + if (len < 0) { + dest->clear(); + return false; + } + + // could be shorter if there was padding + GOOGLE_DCHECK_LE(len, dest_len); + dest->erase(len); + + return true; +} + +bool Base64Unescape(StringPiece src, string* dest) { + return Base64UnescapeInternal(src.data(), src.size(), dest, kUnBase64); +} + +bool WebSafeBase64Unescape(StringPiece src, string* dest) { + return Base64UnescapeInternal(src.data(), src.size(), dest, kUnWebSafeBase64); +} + +int Base64EscapeInternal(const unsigned char *src, int szsrc, + char *dest, int szdest, const char *base64, + bool do_padding) { + static const char kPad64 = '='; + + if (szsrc <= 0) return 0; + + if (szsrc * 4 > szdest * 3) return 0; + + char *cur_dest = dest; + const unsigned char *cur_src = src; + + char *limit_dest = dest + szdest; + const unsigned char *limit_src = src + szsrc; + + // Three bytes of data encodes to four characters of cyphertext. + // So we can pump through three-byte chunks atomically. + while (cur_src < limit_src - 3) { // keep going as long as we have >= 32 bits + uint32 in = BigEndian::Load32(cur_src) >> 8; + + cur_dest[0] = base64[in >> 18]; + in &= 0x3FFFF; + cur_dest[1] = base64[in >> 12]; + in &= 0xFFF; + cur_dest[2] = base64[in >> 6]; + in &= 0x3F; + cur_dest[3] = base64[in]; + + cur_dest += 4; + cur_src += 3; + } + // To save time, we didn't update szdest or szsrc in the loop. So do it now. + szdest = limit_dest - cur_dest; + szsrc = limit_src - cur_src; + + /* now deal with the tail (<=3 bytes) */ + switch (szsrc) { + case 0: + // Nothing left; nothing more to do. + break; + case 1: { + // One byte left: this encodes to two characters, and (optionally) + // two pad characters to round out the four-character cypherblock. + if ((szdest -= 2) < 0) return 0; + uint32 in = cur_src[0]; + cur_dest[0] = base64[in >> 2]; + in &= 0x3; + cur_dest[1] = base64[in << 4]; + cur_dest += 2; + if (do_padding) { + if ((szdest -= 2) < 0) return 0; + cur_dest[0] = kPad64; + cur_dest[1] = kPad64; + cur_dest += 2; + } + break; + } + case 2: { + // Two bytes left: this encodes to three characters, and (optionally) + // one pad character to round out the four-character cypherblock. + if ((szdest -= 3) < 0) return 0; + uint32 in = BigEndian::Load16(cur_src); + cur_dest[0] = base64[in >> 10]; + in &= 0x3FF; + cur_dest[1] = base64[in >> 4]; + in &= 0x00F; + cur_dest[2] = base64[in << 2]; + cur_dest += 3; + if (do_padding) { + if ((szdest -= 1) < 0) return 0; + cur_dest[0] = kPad64; + cur_dest += 1; + } + break; + } + case 3: { + // Three bytes left: same as in the big loop above. We can't do this in + // the loop because the loop above always reads 4 bytes, and the fourth + // byte is past the end of the input. + if ((szdest -= 4) < 0) return 0; + uint32 in = (cur_src[0] << 16) + BigEndian::Load16(cur_src + 1); + cur_dest[0] = base64[in >> 18]; + in &= 0x3FFFF; + cur_dest[1] = base64[in >> 12]; + in &= 0xFFF; + cur_dest[2] = base64[in >> 6]; + in &= 0x3F; + cur_dest[3] = base64[in]; + cur_dest += 4; + break; + } + default: + // Should not be reached: blocks of 4 bytes are handled + // in the while loop before this switch statement. + GOOGLE_LOG(FATAL) << "Logic problem? szsrc = " << szsrc; + break; + } + return (cur_dest - dest); +} + +static const char kBase64Chars[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static const char kWebSafeBase64Chars[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + +int Base64Escape(const unsigned char *src, int szsrc, char *dest, int szdest) { + return Base64EscapeInternal(src, szsrc, dest, szdest, kBase64Chars, true); +} +int WebSafeBase64Escape(const unsigned char *src, int szsrc, char *dest, + int szdest, bool do_padding) { + return Base64EscapeInternal(src, szsrc, dest, szdest, + kWebSafeBase64Chars, do_padding); +} + +void Base64EscapeInternal(const unsigned char* src, int szsrc, + string* dest, bool do_padding, + const char* base64_chars) { + const int calc_escaped_size = + CalculateBase64EscapedLen(szsrc, do_padding); + dest->resize(calc_escaped_size); + const int escaped_len = Base64EscapeInternal(src, szsrc, + string_as_array(dest), + dest->size(), + base64_chars, + do_padding); + GOOGLE_DCHECK_EQ(calc_escaped_size, escaped_len); + dest->erase(escaped_len); +} + +void Base64Escape(const unsigned char *src, int szsrc, + string* dest, bool do_padding) { + Base64EscapeInternal(src, szsrc, dest, do_padding, kBase64Chars); +} + +void WebSafeBase64Escape(const unsigned char *src, int szsrc, + string *dest, bool do_padding) { + Base64EscapeInternal(src, szsrc, dest, do_padding, kWebSafeBase64Chars); +} + +void Base64Escape(StringPiece src, string* dest) { + Base64Escape(reinterpret_cast<const unsigned char*>(src.data()), + src.size(), dest, true); +} + +void WebSafeBase64Escape(StringPiece src, string* dest) { + WebSafeBase64Escape(reinterpret_cast<const unsigned char*>(src.data()), + src.size(), dest, false); +} + +void WebSafeBase64EscapeWithPadding(StringPiece src, string* dest) { + WebSafeBase64Escape(reinterpret_cast<const unsigned char*>(src.data()), + src.size(), dest, true); +} + +// Helper to append a Unicode code point to a string as UTF8, without bringing +// in any external dependencies. +int EncodeAsUTF8Char(uint32 code_point, char* output) { + uint32 tmp = 0; + int len = 0; + if (code_point <= 0x7f) { + tmp = code_point; + len = 1; + } else if (code_point <= 0x07ff) { + tmp = 0x0000c080 | + ((code_point & 0x07c0) << 2) | + (code_point & 0x003f); + len = 2; + } else if (code_point <= 0xffff) { + tmp = 0x00e08080 | + ((code_point & 0xf000) << 4) | + ((code_point & 0x0fc0) << 2) | + (code_point & 0x003f); + len = 3; + } else { + // UTF-16 is only defined for code points up to 0x10FFFF, and UTF-8 is + // normally only defined up to there as well. + tmp = 0xf0808080 | + ((code_point & 0x1c0000) << 6) | + ((code_point & 0x03f000) << 4) | + ((code_point & 0x000fc0) << 2) | + (code_point & 0x003f); + len = 4; + } + tmp = ghtonl(tmp); + memcpy(output, reinterpret_cast<const char*>(&tmp) + sizeof(tmp) - len, len); + return len; +} + +// Table of UTF-8 character lengths, based on first byte +static const unsigned char kUTF8LenTbl[256] = { + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4 +}; + +// Return length of a single UTF-8 source character +int UTF8FirstLetterNumBytes(const char* src, int len) { + if (len == 0) { + return 0; + } + return kUTF8LenTbl[*reinterpret_cast<const uint8*>(src)]; +} + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h index 397122ef..b22066b6 100644 --- a/src/google/protobuf/stubs/strutil.h +++ b/src/google/protobuf/stubs/strutil.h @@ -36,6 +36,7 @@ #include <stdlib.h> #include <vector> #include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/stringpiece.h> namespace google { namespace protobuf { @@ -72,7 +73,33 @@ inline bool ascii_isdigit(char c) { } inline bool ascii_isspace(char c) { - return c == ' '; + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || + c == '\r'; +} + +inline bool ascii_isupper(char c) { + return c >= 'A' && c <= 'Z'; +} + +inline bool ascii_islower(char c) { + return c >= 'a' && c <= 'z'; +} + +inline char ascii_toupper(char c) { + return ascii_islower(c) ? c - ('a' - 'A') : c; +} + +inline char ascii_tolower(char c) { + return ascii_isupper(c) ? c + ('a' - 'A') : c; +} + +inline int hex_digit_to_int(char c) { + /* Assume ASCII. */ + int x = static_cast<unsigned char>(c); + if (x > '9') { + x += 9; + } + return x & 0xf; } // ---------------------------------------------------------------------- @@ -360,12 +387,59 @@ inline uint64 strtou64(const char *nptr, char **endptr, int base) { } // ---------------------------------------------------------------------- +// safe_strtob() // safe_strto32() -// ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT bool safe_int(string text, int32* value_p); +// safe_strtou32() +// safe_strto64() +// safe_strtou64() +// safe_strtof() +// safe_strtod() +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT bool safe_strtob(StringPiece str, bool* value); + +LIBPROTOBUF_EXPORT bool safe_strto32(const string& str, int32* value); +LIBPROTOBUF_EXPORT bool safe_strtou32(const string& str, uint32* value); +inline bool safe_strto32(const char* str, int32* value) { + return safe_strto32(string(str), value); +} +inline bool safe_strto32(StringPiece str, int32* value) { + return safe_strto32(str.ToString(), value); +} +inline bool safe_strtou32(const char* str, uint32* value) { + return safe_strtou32(string(str), value); +} +inline bool safe_strtou32(StringPiece str, uint32* value) { + return safe_strtou32(str.ToString(), value); +} -inline bool safe_strto32(string text, int32* value) { - return safe_int(text, value); +LIBPROTOBUF_EXPORT bool safe_strto64(const string& str, int64* value); +LIBPROTOBUF_EXPORT bool safe_strtou64(const string& str, uint64* value); +inline bool safe_strto64(const char* str, int64* value) { + return safe_strto64(string(str), value); +} +inline bool safe_strto64(StringPiece str, int64* value) { + return safe_strto64(str.ToString(), value); +} +inline bool safe_strtou64(const char* str, uint64* value) { + return safe_strtou64(string(str), value); +} +inline bool safe_strtou64(StringPiece str, uint64* value) { + return safe_strtou64(str.ToString(), value); +} + +LIBPROTOBUF_EXPORT bool safe_strtof(const char* str, float* value); +LIBPROTOBUF_EXPORT bool safe_strtod(const char* str, double* value); +inline bool safe_strtof(const string& str, float* value) { + return safe_strtof(str.c_str(), value); +} +inline bool safe_strtod(const string& str, double* value) { + return safe_strtod(str.c_str(), value); +} +inline bool safe_strtof(StringPiece str, float* value) { + return safe_strtof(str.ToString(), value); +} +inline bool safe_strtod(StringPiece str, double* value) { + return safe_strtod(str.ToString(), value); } // ---------------------------------------------------------------------- @@ -451,6 +525,10 @@ inline char* FastUInt64ToBuffer(uint64 i, char* buffer) { return buffer; } +inline string SimpleBtoa(bool value) { + return value ? "true" : "false"; +} + // ---------------------------------------------------------------------- // SimpleItoa() // Description: converts an integer to a string. @@ -497,28 +575,30 @@ static const int kFloatToBufferSize = 24; namespace strings { +enum PadSpec { + NO_PAD = 1, + ZERO_PAD_2, + ZERO_PAD_3, + ZERO_PAD_4, + ZERO_PAD_5, + ZERO_PAD_6, + ZERO_PAD_7, + ZERO_PAD_8, + ZERO_PAD_9, + ZERO_PAD_10, + ZERO_PAD_11, + ZERO_PAD_12, + ZERO_PAD_13, + ZERO_PAD_14, + ZERO_PAD_15, + ZERO_PAD_16, +}; + struct Hex { uint64 value; - enum PadSpec { - NONE = 1, - ZERO_PAD_2, - ZERO_PAD_3, - ZERO_PAD_4, - ZERO_PAD_5, - ZERO_PAD_6, - ZERO_PAD_7, - ZERO_PAD_8, - ZERO_PAD_9, - ZERO_PAD_10, - ZERO_PAD_11, - ZERO_PAD_12, - ZERO_PAD_13, - ZERO_PAD_14, - ZERO_PAD_15, - ZERO_PAD_16, - } spec; + enum PadSpec spec; template <class Int> - explicit Hex(Int v, PadSpec s = NONE) + explicit Hex(Int v, PadSpec s = NO_PAD) : spec(s) { // Prevent sign-extension by casting integers to // their unsigned counterparts. @@ -571,6 +651,9 @@ struct LIBPROTOBUF_EXPORT AlphaNum { AlphaNum(const string& str) : piece_data_(str.data()), piece_size_(str.size()) {} + AlphaNum(StringPiece str) + : piece_data_(str.data()), piece_size_(str.size()) {} + size_t size() const { return piece_size_; } const char *data() const { return piece_data_; } @@ -692,6 +775,12 @@ string Join(const Range& components, } // ---------------------------------------------------------------------- +// ToHex() +// Return a lower-case hex string representation of the given integer. +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT string ToHex(uint64 num); + +// ---------------------------------------------------------------------- // GlobalReplaceSubstring() // Replaces all instances of a substring in a string. Does nothing // if 'substring' is empty. Returns the number of replacements. @@ -702,6 +791,83 @@ LIBPROTOBUF_EXPORT int GlobalReplaceSubstring(const string& substring, const string& replacement, string* s); +// ---------------------------------------------------------------------- +// Base64Unescape() +// Converts "src" which is encoded in Base64 to its binary equivalent and +// writes it to "dest". If src contains invalid characters, dest is cleared +// and the function returns false. Returns true on success. +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT bool Base64Unescape(StringPiece src, string* dest); + +// ---------------------------------------------------------------------- +// WebSafeBase64Unescape() +// This is a variation of Base64Unescape which uses '-' instead of '+', and +// '_' instead of '/'. src is not null terminated, instead specify len. I +// recommend that slen<szdest, but we honor szdest anyway. +// RETURNS the length of dest, or -1 if src contains invalid chars. + +// The variation that stores into a string clears the string first, and +// returns false (with dest empty) if src contains invalid chars; for +// this version src and dest must be different strings. +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT int WebSafeBase64Unescape(const char* src, int slen, + char* dest, int szdest); +LIBPROTOBUF_EXPORT bool WebSafeBase64Unescape(StringPiece src, string* dest); + +// Return the length to use for the output buffer given to the base64 escape +// routines. Make sure to use the same value for do_padding in both. +// This function may return incorrect results if given input_len values that +// are extremely high, which should happen rarely. +LIBPROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len, + bool do_padding); +// Use this version when calling Base64Escape without a do_padding arg. +LIBPROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len); + +// ---------------------------------------------------------------------- +// Base64Escape() +// WebSafeBase64Escape() +// Encode "src" to "dest" using base64 encoding. +// src is not null terminated, instead specify len. +// 'dest' should have at least CalculateBase64EscapedLen() length. +// RETURNS the length of dest. +// The WebSafe variation use '-' instead of '+' and '_' instead of '/' +// so that we can place the out in the URL or cookies without having +// to escape them. It also has an extra parameter "do_padding", +// which when set to false will prevent padding with "=". +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT int Base64Escape(const unsigned char* src, int slen, + char* dest, int szdest); +LIBPROTOBUF_EXPORT int WebSafeBase64Escape( + const unsigned char* src, int slen, char* dest, + int szdest, bool do_padding); +// Encode src into dest with padding. +LIBPROTOBUF_EXPORT void Base64Escape(StringPiece src, string* dest); +// Encode src into dest web-safely without padding. +LIBPROTOBUF_EXPORT void WebSafeBase64Escape(StringPiece src, string* dest); +// Encode src into dest web-safely with padding. +LIBPROTOBUF_EXPORT void WebSafeBase64EscapeWithPadding(StringPiece src, + string* dest); + +LIBPROTOBUF_EXPORT void Base64Escape(const unsigned char* src, int szsrc, + string* dest, bool do_padding); +LIBPROTOBUF_EXPORT void WebSafeBase64Escape(const unsigned char* src, int szsrc, + string* dest, bool do_padding); + +static const int UTFmax = 4; +// ---------------------------------------------------------------------- +// EncodeAsUTF8Char() +// Helper to append a Unicode code point to a string as UTF8, without bringing +// in any external dependencies. The output buffer must be as least 4 bytes +// large. +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT int EncodeAsUTF8Char(uint32 code_point, char* output); + +// ---------------------------------------------------------------------- +// UTF8FirstLetterNumBytes() +// Length of the first UTF-8 character. +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT int UTF8FirstLetterNumBytes(const char* src, int len); + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/stubs/strutil_unittest.cc b/src/google/protobuf/stubs/strutil_unittest.cc index 7f27dca0..5d62fc4a 100644 --- a/src/google/protobuf/stubs/strutil_unittest.cc +++ b/src/google/protobuf/stubs/strutil_unittest.cc @@ -32,9 +32,15 @@ #include <google/protobuf/stubs/strutil.h> +#include <locale.h> + +#include <google/protobuf/stubs/stl_util.h> #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> -#include <locale.h> + +#ifdef _WIN32 +#define snprintf _snprintf +#endif namespace google { namespace protobuf { @@ -68,6 +74,737 @@ TEST(StringUtilityTest, ImmuneToLocales) { setlocale(LC_NUMERIC, old_locale.c_str()); } +#define EXPECT_EQ_ARRAY(len, x, y, msg) \ + for (int j = 0; j < len; ++j) { \ + EXPECT_EQ(x[j], y[j]) << "" # x << " != " # y \ + << " byte " << j << ": " << msg; \ + } + +static struct { + int plain_length; + const char* plaintext; + const char* cyphertext; +} base64_tests[] = { + // Empty string. + { 0, "", ""}, + + // Basic bit patterns; + // values obtained with "echo -n '...' | uuencode -m test" + + { 1, "\000", "AA==" }, + { 1, "\001", "AQ==" }, + { 1, "\002", "Ag==" }, + { 1, "\004", "BA==" }, + { 1, "\010", "CA==" }, + { 1, "\020", "EA==" }, + { 1, "\040", "IA==" }, + { 1, "\100", "QA==" }, + { 1, "\200", "gA==" }, + + { 1, "\377", "/w==" }, + { 1, "\376", "/g==" }, + { 1, "\375", "/Q==" }, + { 1, "\373", "+w==" }, + { 1, "\367", "9w==" }, + { 1, "\357", "7w==" }, + { 1, "\337", "3w==" }, + { 1, "\277", "vw==" }, + { 1, "\177", "fw==" }, + { 2, "\000\000", "AAA=" }, + { 2, "\000\001", "AAE=" }, + { 2, "\000\002", "AAI=" }, + { 2, "\000\004", "AAQ=" }, + { 2, "\000\010", "AAg=" }, + { 2, "\000\020", "ABA=" }, + { 2, "\000\040", "ACA=" }, + { 2, "\000\100", "AEA=" }, + { 2, "\000\200", "AIA=" }, + { 2, "\001\000", "AQA=" }, + { 2, "\002\000", "AgA=" }, + { 2, "\004\000", "BAA=" }, + { 2, "\010\000", "CAA=" }, + { 2, "\020\000", "EAA=" }, + { 2, "\040\000", "IAA=" }, + { 2, "\100\000", "QAA=" }, + { 2, "\200\000", "gAA=" }, + + { 2, "\377\377", "//8=" }, + { 2, "\377\376", "//4=" }, + { 2, "\377\375", "//0=" }, + { 2, "\377\373", "//s=" }, + { 2, "\377\367", "//c=" }, + { 2, "\377\357", "/+8=" }, + { 2, "\377\337", "/98=" }, + { 2, "\377\277", "/78=" }, + { 2, "\377\177", "/38=" }, + { 2, "\376\377", "/v8=" }, + { 2, "\375\377", "/f8=" }, + { 2, "\373\377", "+/8=" }, + { 2, "\367\377", "9/8=" }, + { 2, "\357\377", "7/8=" }, + { 2, "\337\377", "3/8=" }, + { 2, "\277\377", "v/8=" }, + { 2, "\177\377", "f/8=" }, + + { 3, "\000\000\000", "AAAA" }, + { 3, "\000\000\001", "AAAB" }, + { 3, "\000\000\002", "AAAC" }, + { 3, "\000\000\004", "AAAE" }, + { 3, "\000\000\010", "AAAI" }, + { 3, "\000\000\020", "AAAQ" }, + { 3, "\000\000\040", "AAAg" }, + { 3, "\000\000\100", "AABA" }, + { 3, "\000\000\200", "AACA" }, + { 3, "\000\001\000", "AAEA" }, + { 3, "\000\002\000", "AAIA" }, + { 3, "\000\004\000", "AAQA" }, + { 3, "\000\010\000", "AAgA" }, + { 3, "\000\020\000", "ABAA" }, + { 3, "\000\040\000", "ACAA" }, + { 3, "\000\100\000", "AEAA" }, + { 3, "\000\200\000", "AIAA" }, + { 3, "\001\000\000", "AQAA" }, + { 3, "\002\000\000", "AgAA" }, + { 3, "\004\000\000", "BAAA" }, + { 3, "\010\000\000", "CAAA" }, + { 3, "\020\000\000", "EAAA" }, + { 3, "\040\000\000", "IAAA" }, + { 3, "\100\000\000", "QAAA" }, + { 3, "\200\000\000", "gAAA" }, + + { 3, "\377\377\377", "////" }, + { 3, "\377\377\376", "///+" }, + { 3, "\377\377\375", "///9" }, + { 3, "\377\377\373", "///7" }, + { 3, "\377\377\367", "///3" }, + { 3, "\377\377\357", "///v" }, + { 3, "\377\377\337", "///f" }, + { 3, "\377\377\277", "//+/" }, + { 3, "\377\377\177", "//9/" }, + { 3, "\377\376\377", "//7/" }, + { 3, "\377\375\377", "//3/" }, + { 3, "\377\373\377", "//v/" }, + { 3, "\377\367\377", "//f/" }, + { 3, "\377\357\377", "/+//" }, + { 3, "\377\337\377", "/9//" }, + { 3, "\377\277\377", "/7//" }, + { 3, "\377\177\377", "/3//" }, + { 3, "\376\377\377", "/v//" }, + { 3, "\375\377\377", "/f//" }, + { 3, "\373\377\377", "+///" }, + { 3, "\367\377\377", "9///" }, + { 3, "\357\377\377", "7///" }, + { 3, "\337\377\377", "3///" }, + { 3, "\277\377\377", "v///" }, + { 3, "\177\377\377", "f///" }, + + // Random numbers: values obtained with + // + // #! /bin/bash + // dd bs=$1 count=1 if=/dev/random of=/tmp/bar.random + // od -N $1 -t o1 /tmp/bar.random + // uuencode -m test < /tmp/bar.random + // + // where $1 is the number of bytes (2, 3) + + { 2, "\243\361", "o/E=" }, + { 2, "\024\167", "FHc=" }, + { 2, "\313\252", "y6o=" }, + { 2, "\046\041", "JiE=" }, + { 2, "\145\236", "ZZ4=" }, + { 2, "\254\325", "rNU=" }, + { 2, "\061\330", "Mdg=" }, + { 2, "\245\032", "pRo=" }, + { 2, "\006\000", "BgA=" }, + { 2, "\375\131", "/Vk=" }, + { 2, "\303\210", "w4g=" }, + { 2, "\040\037", "IB8=" }, + { 2, "\261\372", "sfo=" }, + { 2, "\335\014", "3Qw=" }, + { 2, "\233\217", "m48=" }, + { 2, "\373\056", "+y4=" }, + { 2, "\247\232", "p5o=" }, + { 2, "\107\053", "Rys=" }, + { 2, "\204\077", "hD8=" }, + { 2, "\276\211", "vok=" }, + { 2, "\313\110", "y0g=" }, + { 2, "\363\376", "8/4=" }, + { 2, "\251\234", "qZw=" }, + { 2, "\103\262", "Q7I=" }, + { 2, "\142\312", "Yso=" }, + { 2, "\067\211", "N4k=" }, + { 2, "\220\001", "kAE=" }, + { 2, "\152\240", "aqA=" }, + { 2, "\367\061", "9zE=" }, + { 2, "\133\255", "W60=" }, + { 2, "\176\035", "fh0=" }, + { 2, "\032\231", "Gpk=" }, + + { 3, "\013\007\144", "Cwdk" }, + { 3, "\030\112\106", "GEpG" }, + { 3, "\047\325\046", "J9Um" }, + { 3, "\310\160\022", "yHAS" }, + { 3, "\131\100\237", "WUCf" }, + { 3, "\064\342\134", "NOJc" }, + { 3, "\010\177\004", "CH8E" }, + { 3, "\345\147\205", "5WeF" }, + { 3, "\300\343\360", "wOPw" }, + { 3, "\061\240\201", "MaCB" }, + { 3, "\225\333\044", "ldsk" }, + { 3, "\215\137\352", "jV/q" }, + { 3, "\371\147\160", "+Wdw" }, + { 3, "\030\320\051", "GNAp" }, + { 3, "\044\174\241", "JHyh" }, + { 3, "\260\127\037", "sFcf" }, + { 3, "\111\045\033", "SSUb" }, + { 3, "\202\114\107", "gkxH" }, + { 3, "\057\371\042", "L/ki" }, + { 3, "\223\247\244", "k6ek" }, + { 3, "\047\216\144", "J45k" }, + { 3, "\203\070\327", "gzjX" }, + { 3, "\247\140\072", "p2A6" }, + { 3, "\124\115\116", "VE1O" }, + { 3, "\157\162\050", "b3Io" }, + { 3, "\357\223\004", "75ME" }, + { 3, "\052\117\156", "Kk9u" }, + { 3, "\347\154\000", "52wA" }, + { 3, "\303\012\142", "wwpi" }, + { 3, "\060\035\362", "MB3y" }, + { 3, "\130\226\361", "WJbx" }, + { 3, "\173\013\071", "ews5" }, + { 3, "\336\004\027", "3gQX" }, + { 3, "\357\366\234", "7/ac" }, + { 3, "\353\304\111", "68RJ" }, + { 3, "\024\264\131", "FLRZ" }, + { 3, "\075\114\251", "PUyp" }, + { 3, "\315\031\225", "zRmV" }, + { 3, "\154\201\276", "bIG+" }, + { 3, "\200\066\072", "gDY6" }, + { 3, "\142\350\267", "Yui3" }, + { 3, "\033\000\166", "GwB2" }, + { 3, "\210\055\077", "iC0/" }, + { 3, "\341\037\124", "4R9U" }, + { 3, "\161\103\152", "cUNq" }, + { 3, "\270\142\131", "uGJZ" }, + { 3, "\337\076\074", "3z48" }, + { 3, "\375\106\362", "/Uby" }, + { 3, "\227\301\127", "l8FX" }, + { 3, "\340\002\234", "4AKc" }, + { 3, "\121\064\033", "UTQb" }, + { 3, "\157\134\143", "b1xj" }, + { 3, "\247\055\327", "py3X" }, + { 3, "\340\142\005", "4GIF" }, + { 3, "\060\260\143", "MLBj" }, + { 3, "\075\203\170", "PYN4" }, + { 3, "\143\160\016", "Y3AO" }, + { 3, "\313\013\063", "ywsz" }, + { 3, "\174\236\135", "fJ5d" }, + { 3, "\103\047\026", "QycW" }, + { 3, "\365\005\343", "9QXj" }, + { 3, "\271\160\223", "uXCT" }, + { 3, "\362\255\172", "8q16" }, + { 3, "\113\012\015", "SwoN" }, + + // various lengths, generated by this python script: + // + // from string import lowercase as lc + // for i in range(27): + // print '{ %2d, "%s",%s "%s" },' % (i, lc[:i], ' ' * (26-i), + // lc[:i].encode('base64').strip()) + + { 0, "", "" }, + { 1, "a", "YQ==" }, + { 2, "ab", "YWI=" }, + { 3, "abc", "YWJj" }, + { 4, "abcd", "YWJjZA==" }, + { 5, "abcde", "YWJjZGU=" }, + { 6, "abcdef", "YWJjZGVm" }, + { 7, "abcdefg", "YWJjZGVmZw==" }, + { 8, "abcdefgh", "YWJjZGVmZ2g=" }, + { 9, "abcdefghi", "YWJjZGVmZ2hp" }, + { 10, "abcdefghij", "YWJjZGVmZ2hpag==" }, + { 11, "abcdefghijk", "YWJjZGVmZ2hpams=" }, + { 12, "abcdefghijkl", "YWJjZGVmZ2hpamts" }, + { 13, "abcdefghijklm", "YWJjZGVmZ2hpamtsbQ==" }, + { 14, "abcdefghijklmn", "YWJjZGVmZ2hpamtsbW4=" }, + { 15, "abcdefghijklmno", "YWJjZGVmZ2hpamtsbW5v" }, + { 16, "abcdefghijklmnop", "YWJjZGVmZ2hpamtsbW5vcA==" }, + { 17, "abcdefghijklmnopq", "YWJjZGVmZ2hpamtsbW5vcHE=" }, + { 18, "abcdefghijklmnopqr", "YWJjZGVmZ2hpamtsbW5vcHFy" }, + { 19, "abcdefghijklmnopqrs", "YWJjZGVmZ2hpamtsbW5vcHFycw==" }, + { 20, "abcdefghijklmnopqrst", "YWJjZGVmZ2hpamtsbW5vcHFyc3Q=" }, + { 21, "abcdefghijklmnopqrstu", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1" }, + { 22, "abcdefghijklmnopqrstuv", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dg==" }, + { 23, "abcdefghijklmnopqrstuvw", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnc=" }, + { 24, "abcdefghijklmnopqrstuvwx", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4" }, + { 25, "abcdefghijklmnopqrstuvwxy", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eQ==" }, + { 26, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=" }, +}; + +static struct { + const char* plaintext; + const char* cyphertext; +} base64_strings[] = { + // Some google quotes + // Cyphertext created with "uuencode (GNU sharutils) 4.6.3" + // (Note that we're testing the websafe encoding, though, so if + // you add messages, be sure to run "tr -- '+/' '-_'" on the output) + { "I was always good at math and science, and I never realized " + "that was unusual or somehow undesirable. So one of the things " + "I care a lot about is helping to remove that stigma, " + "to show girls that you can be feminine, you can like the things " + "that girls like, but you can also be really good at technology. " + "You can be really good at building things." + " - Marissa Meyer, Newsweek, 2010-12-22" "\n", + + "SSB3YXMgYWx3YXlzIGdvb2QgYXQgbWF0aCBhbmQgc2NpZW5jZSwgYW5kIEkg" + "bmV2ZXIgcmVhbGl6ZWQgdGhhdCB3YXMgdW51c3VhbCBvciBzb21laG93IHVu" + "ZGVzaXJhYmxlLiBTbyBvbmUgb2YgdGhlIHRoaW5ncyBJIGNhcmUgYSBsb3Qg" + "YWJvdXQgaXMgaGVscGluZyB0byByZW1vdmUgdGhhdCBzdGlnbWEsIHRvIHNo" + "b3cgZ2lybHMgdGhhdCB5b3UgY2FuIGJlIGZlbWluaW5lLCB5b3UgY2FuIGxp" + "a2UgdGhlIHRoaW5ncyB0aGF0IGdpcmxzIGxpa2UsIGJ1dCB5b3UgY2FuIGFs" + "c28gYmUgcmVhbGx5IGdvb2QgYXQgdGVjaG5vbG9neS4gWW91IGNhbiBiZSBy" + "ZWFsbHkgZ29vZCBhdCBidWlsZGluZyB0aGluZ3MuIC0gTWFyaXNzYSBNZXll" + "ciwgTmV3c3dlZWssIDIwMTAtMTItMjIK" }, + + { "Typical first year for a new cluster: " + "~0.5 overheating " + "~1 PDU failure " + "~1 rack-move " + "~1 network rewiring " + "~20 rack failures " + "~5 racks go wonky " + "~8 network maintenances " + "~12 router reloads " + "~3 router failures " + "~dozens of minor 30-second blips for dns " + "~1000 individual machine failures " + "~thousands of hard drive failures " + "slow disks, bad memory, misconfigured machines, flaky machines, etc." + " - Jeff Dean, The Joys of Real Hardware" "\n", + + "VHlwaWNhbCBmaXJzdCB5ZWFyIGZvciBhIG5ldyBjbHVzdGVyOiB-MC41IG92" + "ZXJoZWF0aW5nIH4xIFBEVSBmYWlsdXJlIH4xIHJhY2stbW92ZSB-MSBuZXR3" + "b3JrIHJld2lyaW5nIH4yMCByYWNrIGZhaWx1cmVzIH41IHJhY2tzIGdvIHdv" + "bmt5IH44IG5ldHdvcmsgbWFpbnRlbmFuY2VzIH4xMiByb3V0ZXIgcmVsb2Fk" + "cyB-MyByb3V0ZXIgZmFpbHVyZXMgfmRvemVucyBvZiBtaW5vciAzMC1zZWNv" + "bmQgYmxpcHMgZm9yIGRucyB-MTAwMCBpbmRpdmlkdWFsIG1hY2hpbmUgZmFp" + "bHVyZXMgfnRob3VzYW5kcyBvZiBoYXJkIGRyaXZlIGZhaWx1cmVzIHNsb3cg" + "ZGlza3MsIGJhZCBtZW1vcnksIG1pc2NvbmZpZ3VyZWQgbWFjaGluZXMsIGZs" + "YWt5IG1hY2hpbmVzLCBldGMuIC0gSmVmZiBEZWFuLCBUaGUgSm95cyBvZiBS" + "ZWFsIEhhcmR3YXJlCg" }, + + { "I'm the head of the webspam team at Google. " + "That means that if you type your name into Google and get porn back, " + "it's my fault. Unless you're a porn star, in which case porn is a " + "completely reasonable response." + " - Matt Cutts, Google Plus" "\n", + + "SSdtIHRoZSBoZWFkIG9mIHRoZSB3ZWJzcGFtIHRlYW0gYXQgR29vZ2xlLiAg" + "VGhhdCBtZWFucyB0aGF0IGlmIHlvdSB0eXBlIHlvdXIgbmFtZSBpbnRvIEdv" + "b2dsZSBhbmQgZ2V0IHBvcm4gYmFjaywgaXQncyBteSBmYXVsdC4gVW5sZXNz" + "IHlvdSdyZSBhIHBvcm4gc3RhciwgaW4gd2hpY2ggY2FzZSBwb3JuIGlzIGEg" + "Y29tcGxldGVseSByZWFzb25hYmxlIHJlc3BvbnNlLiAtIE1hdHQgQ3V0dHMs" + "IEdvb2dsZSBQbHVzCg" }, + + { "It will still be a long time before machines approach human intelligence. " + "But luckily, machines don't actually have to be intelligent; " + "they just have to fake it. Access to a wealth of information, " + "combined with a rudimentary decision-making capacity, " + "can often be almost as useful. Of course, the results are better yet " + "when coupled with intelligence. A reference librarian with access to " + "a good search engine is a formidable tool." + " - Craig Silverstein, Siemens Pictures of the Future, Spring 2004" "\n", + + "SXQgd2lsbCBzdGlsbCBiZSBhIGxvbmcgdGltZSBiZWZvcmUgbWFjaGluZXMg" + "YXBwcm9hY2ggaHVtYW4gaW50ZWxsaWdlbmNlLiBCdXQgbHVja2lseSwgbWFj" + "aGluZXMgZG9uJ3QgYWN0dWFsbHkgaGF2ZSB0byBiZSBpbnRlbGxpZ2VudDsg" + "dGhleSBqdXN0IGhhdmUgdG8gZmFrZSBpdC4gQWNjZXNzIHRvIGEgd2VhbHRo" + "IG9mIGluZm9ybWF0aW9uLCBjb21iaW5lZCB3aXRoIGEgcnVkaW1lbnRhcnkg" + "ZGVjaXNpb24tbWFraW5nIGNhcGFjaXR5LCBjYW4gb2Z0ZW4gYmUgYWxtb3N0" + "IGFzIHVzZWZ1bC4gT2YgY291cnNlLCB0aGUgcmVzdWx0cyBhcmUgYmV0dGVy" + "IHlldCB3aGVuIGNvdXBsZWQgd2l0aCBpbnRlbGxpZ2VuY2UuIEEgcmVmZXJl" + "bmNlIGxpYnJhcmlhbiB3aXRoIGFjY2VzcyB0byBhIGdvb2Qgc2VhcmNoIGVu" + "Z2luZSBpcyBhIGZvcm1pZGFibGUgdG9vbC4gLSBDcmFpZyBTaWx2ZXJzdGVp" + "biwgU2llbWVucyBQaWN0dXJlcyBvZiB0aGUgRnV0dXJlLCBTcHJpbmcgMjAw" + "NAo" }, + + // Degenerate edge case + { "", + "" }, +}; + +TEST(Base64, EscapeAndUnescape) { + // Check the short strings; this tests the math (and boundaries) + for (int i = 0; i < sizeof(base64_tests) / sizeof(base64_tests[0]); ++i) { + char encode_buffer[100]; + int encode_length; + char decode_buffer[100]; + int decode_length; + int cypher_length; + string decode_str; + + const unsigned char* unsigned_plaintext = + reinterpret_cast<const unsigned char*>(base64_tests[i].plaintext); + + StringPiece plaintext(base64_tests[i].plaintext, + base64_tests[i].plain_length); + + cypher_length = strlen(base64_tests[i].cyphertext); + + // The basic escape function: + memset(encode_buffer, 0, sizeof(encode_buffer)); + encode_length = Base64Escape(unsigned_plaintext, + base64_tests[i].plain_length, + encode_buffer, + sizeof(encode_buffer)); + // Is it of the expected length? + EXPECT_EQ(encode_length, cypher_length); + // Would it have been okay to allocate only CalculateBase64EscapeLen()? + EXPECT_EQ(CalculateBase64EscapedLen(base64_tests[i].plain_length), + encode_length); + + // Is it the expected encoded value? + ASSERT_STREQ(encode_buffer, base64_tests[i].cyphertext); + + // If we encode it into a buffer of exactly the right length... + memset(encode_buffer, 0, sizeof(encode_buffer)); + encode_length = Base64Escape(unsigned_plaintext, + base64_tests[i].plain_length, + encode_buffer, + cypher_length); + // Is it still of the expected length? + EXPECT_EQ(encode_length, cypher_length); + + // And is the value still correct? (i.e., not losing the last byte) + EXPECT_STREQ(encode_buffer, base64_tests[i].cyphertext); + + // If we decode it back: + decode_str.clear(); + EXPECT_TRUE(Base64Unescape( + StringPiece(encode_buffer, cypher_length), &decode_str)); + + // Is it of the expected length? + EXPECT_EQ(base64_tests[i].plain_length, decode_str.length()); + + // Is it the expected decoded value? + EXPECT_EQ(plaintext, decode_str); + + // Let's try with a pre-populated string. + string encoded("this junk should be ignored"); + Base64Escape(string(base64_tests[i].plaintext, + base64_tests[i].plain_length), + &encoded); + EXPECT_EQ(encoded, string(encode_buffer, cypher_length)); + + string decoded("this junk should be ignored"); + EXPECT_TRUE(Base64Unescape( + StringPiece(encode_buffer, cypher_length), &decoded)); + EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); + EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i); + + // Our decoder treats the padding '=' characters at the end as + // optional (but if there are any, there must be the correct + // number of them.) If encode_buffer has any, run some additional + // tests that fiddle with them. + char* first_equals = strchr(encode_buffer, '='); + if (first_equals) { + // How many equals signs does the string start with? + int equals = (*(first_equals+1) == '=') ? 2 : 1; + + // Try chopping off the equals sign(s) entirely. The decoder + // should still be okay with this. + string decoded2("this junk should also be ignored"); + *first_equals = '\0'; + EXPECT_TRUE(Base64Unescape( + StringPiece(encode_buffer, first_equals - encode_buffer), &decoded2)); + EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); + EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i); + + // Now test chopping off the equals sign(s) and adding + // whitespace. Our decoder should still accept this. + decoded2.assign("this junk should be ignored"); + *first_equals = ' '; + *(first_equals+1) = '\0'; + EXPECT_TRUE(Base64Unescape( + StringPiece(encode_buffer, first_equals - encode_buffer + 1), + &decoded2)); + EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); + EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i); + + // Now stick a bad character at the end of the string. The decoder + // should refuse this string. + decoded2.assign("this junk should be ignored"); + *first_equals = '?'; + *(first_equals+1) = '\0'; + EXPECT_TRUE( + !Base64Unescape( + StringPiece(encode_buffer, first_equals - encode_buffer + 1), + &decoded2)); + + int len; + + // Test whitespace mixed with the padding. (eg "AA = = ") The + // decoder should accept this. + if (equals == 2) { + snprintf(first_equals, 6, " = = "); + len = first_equals - encode_buffer + 5; + } else { + snprintf(first_equals, 6, " = "); + len = first_equals - encode_buffer + 3; + } + decoded2.assign("this junk should be ignored"); + EXPECT_TRUE( + Base64Unescape(StringPiece(encode_buffer, len), &decoded2)); + EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); + EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i); + + // Test whitespace mixed with the padding, but with the wrong + // number of equals signs (eg "AA = "). The decoder should + // refuse these strings. + if (equals == 1) { + snprintf(first_equals, 6, " = = "); + len = first_equals - encode_buffer + 5; + } else { + snprintf(first_equals, 6, " = "); + len = first_equals - encode_buffer + 3; + } + EXPECT_TRUE( + !Base64Unescape(StringPiece(encode_buffer, len), &decoded2)); + } + + // Cool! the basic Base64 encoder/decoder works. + // Let's try the alternate alphabet: tr -- '+/' '-_' + + char websafe[100]; + memset(websafe, 0, sizeof(websafe)); + strncpy(websafe, base64_tests[i].cyphertext, cypher_length); + for (int c = 0; c < sizeof(websafe); ++c) { + if ('+' == websafe[c]) { websafe[c] = '-'; } + if ('/' == websafe[c]) { websafe[c] = '_'; } + } + + // The websafe escape function: + memset(encode_buffer, 0, sizeof(encode_buffer)); + encode_length = WebSafeBase64Escape(unsigned_plaintext, + base64_tests[i].plain_length, + encode_buffer, + sizeof(encode_buffer), + true); + // Is it of the expected length? + EXPECT_EQ(encode_length, cypher_length); + EXPECT_EQ( + CalculateBase64EscapedLen(base64_tests[i].plain_length, true), + encode_length); + + // Is it the expected encoded value? + EXPECT_STREQ(encode_buffer, websafe); + + // If we encode it into a buffer of exactly the right length... + memset(encode_buffer, 0, sizeof(encode_buffer)); + encode_length = WebSafeBase64Escape(unsigned_plaintext, + base64_tests[i].plain_length, + encode_buffer, + cypher_length, + true); + // Is it still of the expected length? + EXPECT_EQ(encode_length, cypher_length); + + // And is the value still correct? (i.e., not losing the last byte) + EXPECT_STREQ(encode_buffer, websafe); + + // Let's try the string version of the encoder + encoded = "this junk should be ignored"; + WebSafeBase64Escape( + unsigned_plaintext, base64_tests[i].plain_length, + &encoded, true); + EXPECT_EQ(encoded.size(), cypher_length); + EXPECT_STREQ(encoded.c_str(), websafe); + + // If we decode it back: + memset(decode_buffer, 0, sizeof(decode_buffer)); + decode_length = WebSafeBase64Unescape(encode_buffer, + cypher_length, + decode_buffer, + sizeof(decode_buffer)); + + // Is it of the expected length? + EXPECT_EQ(decode_length, base64_tests[i].plain_length); + + // Is it the expected decoded value? + EXPECT_EQ(0, + memcmp(decode_buffer, base64_tests[i].plaintext, decode_length)); + + // If we decode it into a buffer of exactly the right length... + memset(decode_buffer, 0, sizeof(decode_buffer)); + decode_length = WebSafeBase64Unescape(encode_buffer, + cypher_length, + decode_buffer, + decode_length); + + // Is it still of the expected length? + EXPECT_EQ(decode_length, base64_tests[i].plain_length); + + // And is it the expected decoded value? + EXPECT_EQ(0, + memcmp(decode_buffer, base64_tests[i].plaintext, decode_length)); + + // Try using '.' for the pad character. + for (int c = cypher_length - 1; c >= 0 && '=' == encode_buffer[c]; --c) { + encode_buffer[c] = '.'; + } + + // If we decode it back: + memset(decode_buffer, 0, sizeof(decode_buffer)); + decode_length = WebSafeBase64Unescape(encode_buffer, + cypher_length, + decode_buffer, + sizeof(decode_buffer)); + + // Is it of the expected length? + EXPECT_EQ(decode_length, base64_tests[i].plain_length); + + // Is it the expected decoded value? + EXPECT_EQ(0, + memcmp(decode_buffer, base64_tests[i].plaintext, decode_length)); + + // If we decode it into a buffer of exactly the right length... + memset(decode_buffer, 0, sizeof(decode_buffer)); + decode_length = WebSafeBase64Unescape(encode_buffer, + cypher_length, + decode_buffer, + decode_length); + + // Is it still of the expected length? + EXPECT_EQ(decode_length, base64_tests[i].plain_length); + + // And is it the expected decoded value? + EXPECT_EQ(0, + memcmp(decode_buffer, base64_tests[i].plaintext, decode_length)); + + // Let's try the string version of the decoder + decoded = "this junk should be ignored"; + EXPECT_TRUE(WebSafeBase64Unescape( + StringPiece(encode_buffer, cypher_length), &decoded)); + EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); + EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i); + + // Okay! the websafe Base64 encoder/decoder works. + // Let's try the unpadded version + + for (int c = 0; c < sizeof(websafe); ++c) { + if ('=' == websafe[c]) { + websafe[c] = '\0'; + cypher_length = c; + break; + } + } + + // The websafe escape function: + memset(encode_buffer, 0, sizeof(encode_buffer)); + encode_length = WebSafeBase64Escape(unsigned_plaintext, + base64_tests[i].plain_length, + encode_buffer, + sizeof(encode_buffer), + false); + // Is it of the expected length? + EXPECT_EQ(encode_length, cypher_length); + EXPECT_EQ( + CalculateBase64EscapedLen(base64_tests[i].plain_length, false), + encode_length); + + // Is it the expected encoded value? + EXPECT_STREQ(encode_buffer, websafe); + + // If we encode it into a buffer of exactly the right length... + memset(encode_buffer, 0, sizeof(encode_buffer)); + encode_length = WebSafeBase64Escape(unsigned_plaintext, + base64_tests[i].plain_length, + encode_buffer, + cypher_length, + false); + // Is it still of the expected length? + EXPECT_EQ(encode_length, cypher_length); + + // And is the value still correct? (i.e., not losing the last byte) + EXPECT_STREQ(encode_buffer, websafe); + + // Let's try the (other) string version of the encoder + string plain(base64_tests[i].plaintext, base64_tests[i].plain_length); + encoded = "this junk should be ignored"; + WebSafeBase64Escape(plain, &encoded); + EXPECT_EQ(encoded.size(), cypher_length); + EXPECT_STREQ(encoded.c_str(), websafe); + + // If we decode it back: + memset(decode_buffer, 0, sizeof(decode_buffer)); + decode_length = WebSafeBase64Unescape(encode_buffer, + cypher_length, + decode_buffer, + sizeof(decode_buffer)); + + // Is it of the expected length? + EXPECT_EQ(decode_length, base64_tests[i].plain_length); + + // Is it the expected decoded value? + EXPECT_EQ(0, + memcmp(decode_buffer, base64_tests[i].plaintext, decode_length)); + + // If we decode it into a buffer of exactly the right length... + memset(decode_buffer, 0, sizeof(decode_buffer)); + decode_length = WebSafeBase64Unescape(encode_buffer, + cypher_length, + decode_buffer, + decode_length); + + // Is it still of the expected length? + EXPECT_EQ(decode_length, base64_tests[i].plain_length); + + // And is it the expected decoded value? + EXPECT_EQ(0, + memcmp(decode_buffer, base64_tests[i].plaintext, decode_length)); + + + // Let's try the string version of the decoder + decoded = "this junk should be ignored"; + EXPECT_TRUE(WebSafeBase64Unescape( + StringPiece(encode_buffer, cypher_length), &decoded)); + EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); + EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i); + + // This value works. Try the next. + } + + // Now try the long strings, this tests the streaming + for (int i = 0; i < sizeof(base64_strings) / sizeof(base64_strings[0]); + ++i) { + const unsigned char* unsigned_plaintext = + reinterpret_cast<const unsigned char*>(base64_strings[i].plaintext); + int plain_length = strlen(base64_strings[i].plaintext); + int cypher_length = strlen(base64_strings[i].cyphertext); + vector<char> buffer(cypher_length+1); + int encode_length = WebSafeBase64Escape(unsigned_plaintext, + plain_length, + &buffer[0], + buffer.size(), + false); + EXPECT_EQ(cypher_length, encode_length); + EXPECT_EQ( + CalculateBase64EscapedLen(plain_length, false), encode_length); + buffer[ encode_length ] = '\0'; + EXPECT_STREQ(base64_strings[i].cyphertext, &buffer[0]); + } + + // Verify the behavior when decoding bad data + { + const char* bad_data = "ab-/"; + string buf; + EXPECT_FALSE(Base64Unescape(StringPiece(bad_data), &buf)); + EXPECT_TRUE(!WebSafeBase64Unescape(bad_data, &buf)); + EXPECT_TRUE(buf.empty()); + } +} + } // anonymous namespace } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/stubs/time.cc b/src/google/protobuf/stubs/time.cc new file mode 100644 index 00000000..3319a244 --- /dev/null +++ b/src/google/protobuf/stubs/time.cc @@ -0,0 +1,366 @@ +#include <google/protobuf/stubs/time.h> + +#include <ctime> + +#include <google/protobuf/stubs/stringprintf.h> +#include <google/protobuf/stubs/strutil.h> + +namespace google { +namespace protobuf { +namespace internal { + +namespace { +static const int64 kSecondsPerMinute = 60; +static const int64 kSecondsPerHour = 3600; +static const int64 kSecondsPerDay = kSecondsPerHour * 24; +static const int64 kSecondsPer400Years = + kSecondsPerDay * (400 * 365 + 400 / 4 - 3); +// Seconds from 0001-01-01T00:00:00 to 1970-01-01T:00:00:00 +static const int64 kSecondsFromEraToEpoch = 62135596800LL; +// The range of timestamp values we support. +static const int64 kMinTime = -62135596800LL; // 0001-01-01T00:00:00 +static const int64 kMaxTime = 253402300799LL; // 9999-12-31T23:59:59 + +static const int kNanosPerSecond = 1000000000; +static const int kNanosPerMillisecond = 1000000; +static const int kNanosPerMicrosecond = 1000; + +// Count the seconds from the given year (start at Jan 1, 00:00) to 100 years +// after. +int64 SecondsPer100Years(int year) { + if (year % 400 == 0 || year % 400 > 300) { + return kSecondsPerDay * (100 * 365 + 100 / 4); + } else { + return kSecondsPerDay * (100 * 365 + 100 / 4 - 1); + } +} + +// Count the seconds from the given year (start at Jan 1, 00:00) to 4 years +// after. +int64 SecondsPer4Years(int year) { + if ((year % 100 == 0 || year % 100 > 96) && + !(year % 400 == 0 || year % 400 > 396)) { + // No leap years. + return kSecondsPerDay * (4 * 365); + } else { + // One leap years. + return kSecondsPerDay * (4 * 365 + 1); + } +} + +bool IsLeapYear(int year) { + return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0); +} + +int64 SecondsPerYear(int year) { + return kSecondsPerDay * (IsLeapYear(year) ? 366 : 365); +} + +static const int kDaysInMonth[13] = { + 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +int64 SecondsPerMonth(int month, bool leap) { + if (month == 2 && leap) { + return kSecondsPerDay * (kDaysInMonth[month] + 1); + } + return kSecondsPerDay * kDaysInMonth[month]; +} + +static const int kDaysSinceJan[13] = { + 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, +}; + +bool ValidateDateTime(const DateTime& time) { + if (time.year < 1 || time.year > 9999 || + time.month < 1 || time.month > 12 || + time.day < 1 || time.day > 31 || + time.hour < 0 || time.hour > 23 || + time.minute < 0 || time.minute > 59 || + time.second < 0 || time.second > 59) { + return false; + } + if (time.month == 2 && IsLeapYear(time.year)) { + return time.month <= kDaysInMonth[time.month] + 1; + } else { + return time.month <= kDaysInMonth[time.month]; + } +} + +// Count the number of seconds elapsed from 0001-01-01T00:00:00 to the given +// time. +int64 SecondsSinceCommonEra(const DateTime& time) { + int64 result = 0; + // Years should be between 1 and 9999. + assert(time.year >= 1 && time.year <= 9999); + int year = 1; + if ((time.year - year) >= 400) { + int count_400years = (time.year - year) / 400; + result += kSecondsPer400Years * count_400years; + year += count_400years * 400; + } + while ((time.year - year) >= 100) { + result += SecondsPer100Years(year); + year += 100; + } + while ((time.year - year) >= 4) { + result += SecondsPer4Years(year); + year += 4; + } + while (time.year > year) { + result += SecondsPerYear(year); + ++year; + } + // Months should be between 1 and 12. + assert(time.month >= 1 && time.month <= 12); + int month = time.month; + result += kSecondsPerDay * kDaysSinceJan[month]; + if (month > 2 && IsLeapYear(year)) { + result += kSecondsPerDay; + } + assert(time.day >= 1 && + time.day <= (month == 2 && IsLeapYear(year) + ? kDaysInMonth[month] + 1 + : kDaysInMonth[month])); + result += kSecondsPerDay * (time.day - 1); + result += kSecondsPerHour * time.hour + + kSecondsPerMinute * time.minute + + time.second; + return result; +} + +// Format nanoseconds with either 3, 6, or 9 digits depending on the required +// precision to represent the exact value. +string FormatNanos(int32 nanos) { + if (nanos % kNanosPerMillisecond == 0) { + return StringPrintf("%03d", nanos / kNanosPerMillisecond); + } else if (nanos % kNanosPerMicrosecond == 0) { + return StringPrintf("%06d", nanos / kNanosPerMicrosecond); + } else { + return StringPrintf("%09d", nanos); + } +} + +// Parses an integer from a null-terminated char sequence. The method +// consumes at most "width" chars. Returns a pointer after the consumed +// integer, or NULL if the data does not start with an integer or the +// integer value does not fall in the range of [min_value, max_value]. +const char* ParseInt(const char* data, int width, int min_value, + int max_value, int* result) { + if (!ascii_isdigit(*data)) { + return NULL; + } + int value = 0; + for (int i = 0; i < width; ++i, ++data) { + if (ascii_isdigit(*data)) { + value = value * 10 + (*data - '0'); + } else { + break; + } + } + if (value >= min_value && value <= max_value) { + *result = value; + return data; + } else { + return NULL; + } +} + +// Consumes the fractional parts of a second into nanos. For example, +// "010" will be parsed to 10000000 nanos. +const char* ParseNanos(const char* data, int32* nanos) { + if (!ascii_isdigit(*data)) { + return NULL; + } + int value = 0; + int len = 0; + // Consume as many digits as there are but only take the first 9 into + // account. + while (ascii_isdigit(*data)) { + if (len < 9) { + value = value * 10 + *data - '0'; + } + ++len; + ++data; + } + while (len < 9) { + value = value * 10; + ++len; + } + *nanos = value; + return data; +} + +const char* ParseTimezoneOffset(const char* data, int64* offset) { + // Accept format "HH:MM". E.g., "08:00" + int hour; + if ((data = ParseInt(data, 2, 0, 23, &hour)) == NULL) { + return NULL; + } + if (*data++ != ':') { + return NULL; + } + int minute; + if ((data = ParseInt(data, 2, 0, 59, &minute)) == NULL) { + return NULL; + } + *offset = (hour * 60 + minute) * 60; + return data; +} +} // namespace + +bool SecondsToDateTime(int64 seconds, DateTime* time) { + if (seconds < kMinTime || seconds > kMaxTime) { + return false; + } + // It's easier to calcuate the DateTime starting from 0001-01-01T00:00:00 + seconds = seconds + kSecondsFromEraToEpoch; + int year = 1; + if (seconds >= kSecondsPer400Years) { + int count_400years = seconds / kSecondsPer400Years; + year += 400 * count_400years; + seconds %= kSecondsPer400Years; + } + while (seconds >= SecondsPer100Years(year)) { + seconds -= SecondsPer100Years(year); + year += 100; + } + while (seconds >= SecondsPer4Years(year)) { + seconds -= SecondsPer4Years(year); + year += 4; + } + while (seconds >= SecondsPerYear(year)) { + seconds -= SecondsPerYear(year); + year += 1; + } + bool leap = IsLeapYear(year); + int month = 1; + while (seconds >= SecondsPerMonth(month, leap)) { + seconds -= SecondsPerMonth(month, leap); + ++month; + } + int day = 1 + seconds / kSecondsPerDay; + seconds %= kSecondsPerDay; + int hour = seconds / kSecondsPerHour; + seconds %= kSecondsPerHour; + int minute = seconds / kSecondsPerMinute; + seconds %= kSecondsPerMinute; + time->year = year; + time->month = month; + time->day = day; + time->hour = hour; + time->minute = minute; + time->second = static_cast<int>(seconds); + return true; +} + +bool DateTimeToSeconds(const DateTime& time, int64* seconds) { + if (!ValidateDateTime(time)) { + return false; + } + *seconds = SecondsSinceCommonEra(time) - kSecondsFromEraToEpoch; + return true; +} + +void GetCurrentTime(int64* seconds, int32* nanos) { + // TODO(xiaofeng): Improve the accuracy of this implementation (or just + // remove this method from protobuf). + *seconds = time(NULL); + *nanos = 0; +} + +string FormatTime(int64 seconds, int32 nanos) { + DateTime time; + if (nanos < 0 || nanos > 999999999 || !SecondsToDateTime(seconds, &time)) { + return "InvalidTime"; + } + string result = StringPrintf("%04d-%02d-%02dT%02d:%02d:%02d", + time.year, time.month, time.day, + time.hour, time.minute, time.second); + if (nanos != 0) { + result += "." + FormatNanos(nanos); + } + return result + "Z"; +} + +bool ParseTime(const string& value, int64* seconds, int32* nanos) { + DateTime time; + const char* data = value.c_str(); + // We only accept: + // Z-normalized: 2015-05-20T13:29:35.120Z + // With UTC offset: 2015-05-20T13:29:35.120-08:00 + + // Parse year + if ((data = ParseInt(data, 4, 1, 9999, &time.year)) == NULL) { + return false; + } + // Expect '-' + if (*data++ != '-') return false; + // Parse month + if ((data = ParseInt(data, 2, 1, 12, &time.month)) == NULL) { + return false; + } + // Expect '-' + if (*data++ != '-') return false; + // Parse day + if ((data = ParseInt(data, 2, 1, 31, &time.day)) == NULL) { + return false; + } + // Expect 'T' + if (*data++ != 'T') return false; + // Parse hour + if ((data = ParseInt(data, 2, 0, 23, &time.hour)) == NULL) { + return false; + } + // Expect ':' + if (*data++ != ':') return false; + // Parse minute + if ((data = ParseInt(data, 2, 0, 59, &time.minute)) == NULL) { + return false; + } + // Expect ':' + if (*data++ != ':') return false; + // Parse second + if ((data = ParseInt(data, 2, 0, 59, &time.second)) == NULL) { + return false; + } + if (!DateTimeToSeconds(time, seconds)) { + return false; + } + // Parse nanoseconds. + if (*data == '.') { + ++data; + // Parse nanoseconds. + if ((data = ParseNanos(data, nanos)) == NULL) { + return false; + } + } else { + *nanos = 0; + } + // Parse UTC offsets. + if (*data == 'Z') { + ++data; + } else if (*data == '+') { + ++data; + int64 offset; + if ((data = ParseTimezoneOffset(data, &offset)) == NULL) { + return false; + } + *seconds -= offset; + } else if (*data == '-') { + ++data; + int64 offset; + if ((data = ParseTimezoneOffset(data, &offset)) == NULL) { + return false; + } + *seconds += offset; + } else { + return false; + } + // Done with parsing. + return *data == 0; +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/time.h b/src/google/protobuf/stubs/time.h new file mode 100644 index 00000000..20a6b56d --- /dev/null +++ b/src/google/protobuf/stubs/time.h @@ -0,0 +1,75 @@ +// 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_STUBS_TIME_H_ +#define GOOGLE_PROTOBUF_STUBS_TIME_H_ + +#include <google/protobuf/stubs/common.h> + +namespace google { +namespace protobuf { +namespace internal { + +struct DateTime { + int year; + int month; + int day; + int hour; + int minute; + int second; +}; + +// Converts a timestamp (seconds elapsed since 1970-01-01T00:00:00, could be +// negative to represent time before 1970-01-01) to DateTime. Returns false +// if the timestamp is not in the range between 0001-01-01T00:00:00 and +// 9999-12-31T23:59:59. +bool LIBPROTOBUF_EXPORT SecondsToDateTime(int64 seconds, DateTime* time); +// Converts DateTime to a timestamp (seconds since 1970-01-01T00:00:00). +// Returns false if the DateTime is not valid or is not in the valid range. +bool LIBPROTOBUF_EXPORT DateTimeToSeconds(const DateTime& time, int64* seconds); + +void LIBPROTOBUF_EXPORT GetCurrentTime(int64* seconds, int32* nanos); + +// Formats a time string in RFC3339 fromat. +// +// For example, "2015-05-20T13:29:35.120Z". For nanos, 0, 3, 6 or 9 fractional +// digits will be used depending on how many are required to represent the exact +// value. +// +// Note that "nanos" must in the range of [0, 999999999]. +string LIBPROTOBUF_EXPORT FormatTime(int64 seconds, int32 nanos); +// Parses a time string. This method accepts RFC3339 date/time string with UTC +// offset. For example, "2015-05-20T13:29:35.120-08:00". +bool LIBPROTOBUF_EXPORT ParseTime(const string& vaule, int64* seconds, int32* nanos); + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_TIME_H_ diff --git a/src/google/protobuf/stubs/time_test.cc b/src/google/protobuf/stubs/time_test.cc new file mode 100644 index 00000000..59e9d1c7 --- /dev/null +++ b/src/google/protobuf/stubs/time_test.cc @@ -0,0 +1,208 @@ +// 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/stubs/time.h> + +#include <google/protobuf/testing/googletest.h> +#include <gtest/gtest.h> + +namespace google { +namespace protobuf { +namespace internal { +namespace { +static const int64 kSecondsPerDay = 3600 * 24; + +// For DateTime, tests will mostly focuse on the date part because that's +// the tricky one. +int64 CreateTimestamp(int year, int month, int day) { + DateTime time; + time.year = year; + time.month = month; + time.day = day; + time.hour = time.minute = time.second = 0; + int64 result; + GOOGLE_CHECK(DateTimeToSeconds(time, &result)); + // Check that a roundtrip produces the same result. + GOOGLE_CHECK(SecondsToDateTime(result, &time)); + GOOGLE_CHECK(time.year == year); + GOOGLE_CHECK(time.month == month); + GOOGLE_CHECK(time.day == day); + return result; +} + +TEST(DateTimeTest, SimpleTime) { + DateTime time; + ASSERT_TRUE(SecondsToDateTime(1, &time)); + EXPECT_EQ(1970, time.year); + EXPECT_EQ(1, time.month); + EXPECT_EQ(1, time.day); + EXPECT_EQ(0, time.hour); + EXPECT_EQ(0, time.minute); + EXPECT_EQ(1, time.second); + int64 seconds; + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + EXPECT_EQ(1, seconds); + + ASSERT_TRUE(SecondsToDateTime(-1, &time)); + EXPECT_EQ(1969, time.year); + EXPECT_EQ(12, time.month); + EXPECT_EQ(31, time.day); + EXPECT_EQ(23, time.hour); + EXPECT_EQ(59, time.minute); + EXPECT_EQ(59, time.second); + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + EXPECT_EQ(-1, seconds); + + DateTime start, end; + start.year = 1; + start.month = 1; + start.day = 1; + start.hour = 0; + start.minute = 0; + start.second = 0; + end.year = 9999; + end.month = 12; + end.day = 31; + end.hour = 23; + end.minute = 59; + end.second = 59; + int64 start_time, end_time; + ASSERT_TRUE(DateTimeToSeconds(start, &start_time)); + ASSERT_TRUE(DateTimeToSeconds(end, &end_time)); + EXPECT_EQ(315537897599LL, end_time - start_time); + ASSERT_TRUE(SecondsToDateTime(start_time, &time)); + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + EXPECT_EQ(start_time, seconds); + ASSERT_TRUE(SecondsToDateTime(end_time, &time)); + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + EXPECT_EQ(end_time, seconds); +} + +TEST(DateTimeTest, DayInMonths) { + // Check that month boundaries are handled correctly. + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 1, 1) - CreateTimestamp(2014, 12, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 2, 1) - CreateTimestamp(2015, 1, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 3, 1) - CreateTimestamp(2015, 2, 28)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 4, 1) - CreateTimestamp(2015, 3, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 5, 1) - CreateTimestamp(2015, 4, 30)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 6, 1) - CreateTimestamp(2015, 5, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 7, 1) - CreateTimestamp(2015, 6, 30)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 8, 1) - CreateTimestamp(2015, 7, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 9, 1) - CreateTimestamp(2015, 8, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 10, 1) - CreateTimestamp(2015, 9, 30)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 11, 1) - CreateTimestamp(2015, 10, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 12, 1) - CreateTimestamp(2015, 11, 30)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2016, 1, 1) - CreateTimestamp(2015, 12, 31)); +} + +TEST(DateTimeTest, LeapYear) { + // Non-leap year. + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 3, 1) - CreateTimestamp(2015, 2, 28)); + // Leap year. + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2016, 3, 1) - CreateTimestamp(2016, 2, 29)); + // Non-leap year. + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2100, 3, 1) - CreateTimestamp(2100, 2, 28)); + // Leap year. + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2400, 3, 1) - CreateTimestamp(2400, 2, 29)); +} + +TEST(DateTimeTest, StringFormat) { + DateTime start, end; + start.year = 1; + start.month = 1; + start.day = 1; + start.hour = 0; + start.minute = 0; + start.second = 0; + end.year = 9999; + end.month = 12; + end.day = 31; + end.hour = 23; + end.minute = 59; + end.second = 59; + int64 start_time, end_time; + ASSERT_TRUE(DateTimeToSeconds(start, &start_time)); + ASSERT_TRUE(DateTimeToSeconds(end, &end_time)); + + EXPECT_EQ("0001-01-01T00:00:00Z", FormatTime(start_time, 0)); + EXPECT_EQ("9999-12-31T23:59:59Z", FormatTime(end_time, 0)); + + // Make sure the nanoseconds part is formated correctly. + EXPECT_EQ("1970-01-01T00:00:00.010Z", FormatTime(0, 10000000)); + EXPECT_EQ("1970-01-01T00:00:00.000010Z", FormatTime(0, 10000)); + EXPECT_EQ("1970-01-01T00:00:00.000000010Z", FormatTime(0, 10)); +} + +TEST(DateTimeTest, ParseString) { + int64 seconds; + int32 nanos; + ASSERT_TRUE(ParseTime("0001-01-01T00:00:00Z", &seconds, &nanos)); + EXPECT_EQ("0001-01-01T00:00:00Z", FormatTime(seconds, nanos)); + ASSERT_TRUE(ParseTime("9999-12-31T23:59:59.999999999Z", &seconds, &nanos)); + EXPECT_EQ("9999-12-31T23:59:59.999999999Z", FormatTime(seconds, nanos)); + + // Test time zone offsets. + ASSERT_TRUE(ParseTime("1970-01-01T00:00:00-08:00", &seconds, &nanos)); + EXPECT_EQ("1970-01-01T08:00:00Z", FormatTime(seconds, nanos)); + ASSERT_TRUE(ParseTime("1970-01-01T00:00:00+08:00", &seconds, &nanos)); + EXPECT_EQ("1969-12-31T16:00:00Z", FormatTime(seconds, nanos)); + + // Test nanoseconds. + ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.01Z", &seconds, &nanos)); + EXPECT_EQ("1970-01-01T00:00:00.010Z", FormatTime(seconds, nanos)); + ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.00001-08:00", &seconds, &nanos)); + EXPECT_EQ("1970-01-01T08:00:00.000010Z", FormatTime(seconds, nanos)); + ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.00000001+08:00", &seconds, &nanos)); + EXPECT_EQ("1969-12-31T16:00:00.000000010Z", FormatTime(seconds, nanos)); + // Fractional parts less than 1 nanosecond will be ignored. + ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.0123456789Z", &seconds, &nanos)); + EXPECT_EQ("1970-01-01T00:00:00.012345678Z", FormatTime(seconds, nanos)); +} + +} // namespace +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/testing/googletest.cc b/src/google/protobuf/testing/googletest.cc index 64328063..b8bd790b 100644 --- a/src/google/protobuf/testing/googletest.cc +++ b/src/google/protobuf/testing/googletest.cc @@ -66,7 +66,14 @@ namespace protobuf { string TestSourceDir() { #ifndef GOOGLE_THIRD_PARTY_PROTOBUF -#ifdef _MSC_VER +#ifndef _MSC_VER + // automake sets the "srcdir" environment variable. + char* result = getenv("srcdir"); + if (result != NULL) { + return result; + } +#endif // _MSC_VER + // Look for the "src" directory. string prefix = "."; @@ -80,16 +87,6 @@ string TestSourceDir() { } return prefix + "/src"; #else - // automake sets the "srcdir" environment variable. - char* result = getenv("srcdir"); - if (result == NULL) { - // Otherwise, the test must be run from the source directory. - return "."; - } else { - return result; - } -#endif -#else return "third_party/protobuf/src"; #endif // GOOGLE_THIRD_PARTY_PROTOBUF } diff --git a/src/google/protobuf/testing/zcgunzip.cc b/src/google/protobuf/testing/zcgunzip.cc index daf74ff1..c9d085c8 100644 --- a/src/google/protobuf/testing/zcgunzip.cc +++ b/src/google/protobuf/testing/zcgunzip.cc @@ -38,8 +38,6 @@ // Reads gzip stream on standard input and writes decompressed data to standard // output. -#include "config.h" - #include <assert.h> #include <stdio.h> #include <stdlib.h> diff --git a/src/google/protobuf/testing/zcgzip.cc b/src/google/protobuf/testing/zcgzip.cc index a4101999..e910f321 100644 --- a/src/google/protobuf/testing/zcgzip.cc +++ b/src/google/protobuf/testing/zcgzip.cc @@ -38,8 +38,6 @@ // Reads data on standard input and writes compressed gzip stream to standard // output. -#include "config.h" - #include <stdio.h> #include <stdlib.h> #include <fcntl.h> diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index 61dfa5d6..4d8c1f91 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -1880,7 +1880,7 @@ void TextFormat::Printer::PrintUnknownFields( generator.Print(field_number); generator.Print(": 0x"); generator.Print( - StrCat(strings::Hex(field.fixed32(), strings::Hex::ZERO_PAD_8))); + StrCat(strings::Hex(field.fixed32(), strings::ZERO_PAD_8))); if (single_line_mode_) { generator.Print(" "); } else { @@ -1892,7 +1892,7 @@ void TextFormat::Printer::PrintUnknownFields( generator.Print(field_number); generator.Print(": 0x"); generator.Print( - StrCat(strings::Hex(field.fixed64(), strings::Hex::ZERO_PAD_16))); + StrCat(strings::Hex(field.fixed64(), strings::ZERO_PAD_16))); if (single_line_mode_) { generator.Print(" "); } else { diff --git a/src/google/protobuf/util/field_comparator.cc b/src/google/protobuf/util/field_comparator.cc new file mode 100644 index 00000000..9f613265 --- /dev/null +++ b/src/google/protobuf/util/field_comparator.cc @@ -0,0 +1,188 @@ +// 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. + +// Author: ksroka@google.com (Krzysztof Sroka) + +#include <google/protobuf/util/field_comparator.h> + +#include <string> + +#include <google/protobuf/descriptor.h> +#include <google/protobuf/message.h> +#include <google/protobuf/stubs/map_util.h> +#include <google/protobuf/stubs/mathlimits.h> +#include <google/protobuf/stubs/mathutil.h> + +namespace google { +namespace protobuf { +namespace util { + +FieldComparator::FieldComparator() {} +FieldComparator::~FieldComparator() {} + +DefaultFieldComparator::DefaultFieldComparator() + : float_comparison_(EXACT), + treat_nan_as_equal_(false), + has_default_tolerance_(false) { +} + +DefaultFieldComparator::~DefaultFieldComparator() {} + +FieldComparator::ComparisonResult DefaultFieldComparator::Compare( + const google::protobuf::Message& message_1, + const google::protobuf::Message& message_2, + const google::protobuf::FieldDescriptor* field, + int index_1, int index_2, + const google::protobuf::util::FieldContext* field_context) { + const Reflection* reflection_1 = message_1.GetReflection(); + const Reflection* reflection_2 = message_2.GetReflection(); + + switch (field->cpp_type()) { +#define COMPARE_FIELD(METHOD) \ + if (field->is_repeated()) { \ + return ResultFromBoolean(Compare##METHOD( \ + *field, \ + reflection_1->GetRepeated##METHOD(message_1, field, index_1), \ + reflection_2->GetRepeated##METHOD(message_2, field, index_2))); \ + } else { \ + return ResultFromBoolean(Compare##METHOD( \ + *field, \ + reflection_1->Get##METHOD(message_1, field), \ + reflection_2->Get##METHOD(message_2, field))); \ + } \ + break; // Make sure no fall-through is introduced. + + case FieldDescriptor::CPPTYPE_BOOL: + COMPARE_FIELD(Bool); + case FieldDescriptor::CPPTYPE_DOUBLE: + COMPARE_FIELD(Double); + case FieldDescriptor::CPPTYPE_ENUM: + COMPARE_FIELD(Enum); + case FieldDescriptor::CPPTYPE_FLOAT: + COMPARE_FIELD(Float); + case FieldDescriptor::CPPTYPE_INT32: + COMPARE_FIELD(Int32); + case FieldDescriptor::CPPTYPE_INT64: + COMPARE_FIELD(Int64); + case FieldDescriptor::CPPTYPE_STRING: + COMPARE_FIELD(String); + case FieldDescriptor::CPPTYPE_UINT32: + COMPARE_FIELD(UInt32); + case FieldDescriptor::CPPTYPE_UINT64: + COMPARE_FIELD(UInt64); + +#undef COMPARE_FIELD + + case FieldDescriptor::CPPTYPE_MESSAGE: + return RECURSE; + + default: + GOOGLE_LOG(FATAL) << "No comparison code for field " << field->full_name() + << " of CppType = " << field->cpp_type(); + return DIFFERENT; + } +} + +void DefaultFieldComparator::SetDefaultFractionAndMargin(double fraction, + double margin) { + default_tolerance_ = Tolerance(fraction, margin); + has_default_tolerance_ = true; +} + +void DefaultFieldComparator::SetFractionAndMargin(const FieldDescriptor* field, + double fraction, + double margin) { + GOOGLE_CHECK(FieldDescriptor::CPPTYPE_FLOAT == field->cpp_type() || + FieldDescriptor::CPPTYPE_DOUBLE == field->cpp_type()) + << "Field has to be float or double type. Field name is: " + << field->full_name(); + map_tolerance_[field] = Tolerance(fraction, margin); +} + +bool DefaultFieldComparator::CompareDouble(const FieldDescriptor& field, + double value_1, double value_2) { + return CompareDoubleOrFloat(field, value_1, value_2); +} + +bool DefaultFieldComparator::CompareEnum(const FieldDescriptor& field, + const EnumValueDescriptor* value_1, + const EnumValueDescriptor* value_2) { + return value_1->number() == value_2->number(); +} + +bool DefaultFieldComparator::CompareFloat(const FieldDescriptor& field, + float value_1, float value_2) { + return CompareDoubleOrFloat(field, value_1, value_2); +} + +template<typename T> +bool DefaultFieldComparator::CompareDoubleOrFloat(const FieldDescriptor& field, + T value_1, T value_2) { + if (value_1 == value_2) { + // Covers +inf and -inf (which are not within margin or fraction of + // themselves), and is a shortcut for finite values. + return true; + } else if (float_comparison_ == EXACT) { + if (treat_nan_as_equal_ && + MathLimits<T>::IsNaN(value_1) && MathLimits<T>::IsNaN(value_2)) { + return true; + } + return false; + } else { + if (treat_nan_as_equal_ && + MathLimits<T>::IsNaN(value_1) && MathLimits<T>::IsNaN(value_2)) { + return true; + } + // float_comparison_ == APPROXIMATE covers two use cases. + Tolerance* tolerance = FindOrNull(map_tolerance_, &field); + if (tolerance == NULL && has_default_tolerance_) { + tolerance = &default_tolerance_; + } + if (tolerance == NULL) { + return MathUtil::AlmostEquals(value_1, value_2); + } else { + // Use user-provided fraction and margin. Since they are stored as + // doubles, we explicitely cast them to types of values provided. This + // is very likely to fail if provided values are not numeric. + return MathUtil::WithinFractionOrMargin( + value_1, value_2, static_cast<T>(tolerance->fraction), + static_cast<T>(tolerance->margin)); + } + } +} + +FieldComparator::ComparisonResult DefaultFieldComparator::ResultFromBoolean( + bool boolean_result) const { + return boolean_result ? FieldComparator::SAME : FieldComparator::DIFFERENT; +} + +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/field_comparator.h b/src/google/protobuf/util/field_comparator.h new file mode 100644 index 00000000..ee676265 --- /dev/null +++ b/src/google/protobuf/util/field_comparator.h @@ -0,0 +1,259 @@ +// 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. + +// Author: ksroka@google.com (Krzysztof Sroka) + +#ifndef GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__ +#define GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__ + +#include <map> +#include <string> + +#include <google/protobuf/stubs/common.h> + +namespace google { +namespace protobuf { + +class Message; +class EnumValueDescriptor; +class FieldDescriptor; + +namespace util { + +class FieldContext; + +// Base class specifying the interface for comparing protocol buffer fields. +// Regular users should consider using or subclassing DefaultFieldComparator +// rather than this interface. +// Currently, this does not support comparing unknown fields. +class LIBPROTOBUF_EXPORT FieldComparator { + public: + FieldComparator(); + virtual ~FieldComparator(); + + enum ComparisonResult { + SAME, // Compared fields are equal. In case of comparing submessages, + // user should not recursively compare their contents. + DIFFERENT, // Compared fields are different. In case of comparing + // submessages, user should not recursively compare their + // contents. + RECURSE, // Compared submessages need to be compared recursively. + // FieldComparator does not specify the semantics of recursive + // comparison. This value should not be returned for simple + // values. + }; + + // Compares the values of a field in two protocol buffer messages. + // Returns SAME or DIFFERENT for simple values, and SAME, DIFFERENT or RECURSE + // for submessages. Returning RECURSE for fields not being submessages is + // illegal. + // In case the given FieldDescriptor points to a repeated field, the indices + // need to be valid. Otherwise they should be ignored. + // + // FieldContext contains information about the specific instances of the + // fields being compared, versus FieldDescriptor which only contains general + // type information about the fields. + virtual ComparisonResult Compare( + const google::protobuf::Message& message_1, + const google::protobuf::Message& message_2, + const google::protobuf::FieldDescriptor* field, + int index_1, int index_2, + const google::protobuf::util::FieldContext* field_context) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldComparator); +}; + +// Basic implementation of FieldComparator. Supports four modes of floating +// point value comparison: exact, approximate using MathUtil::AlmostEqual +// method, and arbitrarilly precise using MathUtil::WithinFracionOrMargin. +class LIBPROTOBUF_EXPORT DefaultFieldComparator : public FieldComparator { + public: + enum FloatComparison { + EXACT, // Floats and doubles are compared exactly. + APPROXIMATE, // Floats and doubles are compared using the + // MathUtil::AlmostEqual method or + // MathUtil::WithinFractionOrMargin method. + // TODO(ksroka): Introduce third value to differenciate uses of AlmostEqual + // and WithinFractionOrMargin. + }; + + // Creates new comparator with float comparison set to EXACT. + DefaultFieldComparator(); + + virtual ~DefaultFieldComparator(); + + virtual ComparisonResult Compare( + const google::protobuf::Message& message_1, + const google::protobuf::Message& message_2, + const google::protobuf::FieldDescriptor* field, + int index_1, int index_2, + const google::protobuf::util::FieldContext* field_context); + + void set_float_comparison(FloatComparison float_comparison) { + float_comparison_ = float_comparison; + } + + FloatComparison float_comparison() const { + return float_comparison_; + } + + // Set whether the FieldComparator shall treat floats or doubles that are both + // NaN as equal (treat_nan_as_equal = true) or as different + // (treat_nan_as_equal = false). Default is treating NaNs always as different. + void set_treat_nan_as_equal(bool treat_nan_as_equal) { + treat_nan_as_equal_ = treat_nan_as_equal; + } + + bool treat_nan_as_equal() const { + return treat_nan_as_equal_; + } + + // Sets the fraction and margin for the float comparison of a given field. + // Uses MathUtil::WithinFractionOrMargin to compare the values. + // + // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or + // field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT + // REQUIRES: float_comparison_ == APPROXIMATE + void SetFractionAndMargin(const FieldDescriptor* field, double fraction, + double margin); + + // Sets the fraction and margin for the float comparison of all float and + // double fields, unless a field has been given a specific setting via + // SetFractionAndMargin() above. + // Uses MathUtil::WithinFractionOrMargin to compare the values. + // + // REQUIRES: float_comparison_ == APPROXIMATE + void SetDefaultFractionAndMargin(double fraction, double margin); + + private: + // Defines the tolerance for floating point comparison (fraction and margin). + struct Tolerance { + double fraction; + double margin; + Tolerance() + : fraction(0.0), + margin(0.0) {} + Tolerance(double f, double m) + : fraction(f), + margin(m) {} + }; + + // Defines the map to store the tolerances for floating point comparison. + typedef map<const FieldDescriptor*, Tolerance> ToleranceMap; + + // The following methods get executed when CompareFields is called for the + // basic types (instead of submessages). They return true on success. One + // can use ResultFromBoolean() to convert that boolean to a ComparisonResult + // value. + bool CompareBool(const google::protobuf::FieldDescriptor& field, + bool value_1, bool value_2) { + return value_1 == value_2; + } + + // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and + // CompareFloat. + bool CompareDouble(const google::protobuf::FieldDescriptor& field, + double value_1, double value_2); + + bool CompareEnum(const google::protobuf::FieldDescriptor& field, + const EnumValueDescriptor* value_1, + const EnumValueDescriptor* value_2); + + // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and + // CompareFloat. + bool CompareFloat(const google::protobuf::FieldDescriptor& field, + float value_1, float value_2); + + bool CompareInt32(const google::protobuf::FieldDescriptor& field, + int32 value_1, int32 value_2) { + return value_1 == value_2; + } + + bool CompareInt64(const google::protobuf::FieldDescriptor& field, + int64 value_1, int64 value_2) { + return value_1 == value_2; + } + + bool CompareString(const google::protobuf::FieldDescriptor& field, + const string& value_1, const string& value_2) { + return value_1 == value_2; + } + + bool CompareUInt32(const google::protobuf::FieldDescriptor& field, + uint32 value_1, uint32 value_2) { + return value_1 == value_2; + } + + bool CompareUInt64(const google::protobuf::FieldDescriptor& field, + uint64 value_1, uint64 value_2) { + return value_1 == value_2; + } + + // This function is used by CompareDouble and CompareFloat to avoid code + // duplication. There are no checks done against types of the values passed, + // but it's likely to fail if passed non-numeric arguments. + template<typename T> + bool CompareDoubleOrFloat(const google::protobuf::FieldDescriptor& field, + T value_1, T value_2); + + // Returns FieldComparator::SAME if boolean_result is true and + // FieldComparator::DIFFERENT otherwise. + ComparisonResult ResultFromBoolean(bool boolean_result) const; + + FloatComparison float_comparison_; + + // If true, floats and doubles that are both NaN are considered to be + // equal. Otherwise, two floats or doubles that are NaN are considered to be + // different. + bool treat_nan_as_equal_; + + // True iff default_tolerance_ has been explicitly set. + // + // If false, then the default tolerance for flaots and doubles is that which + // is used by MathUtil::AlmostEquals(). + bool has_default_tolerance_; + + // Default float/double tolerance. Only meaningful if + // has_default_tolerance_ == true. + Tolerance default_tolerance_; + + // Field-specific float/double tolerances, which override any default for + // those particular fields. + ToleranceMap map_tolerance_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultFieldComparator); +}; + +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__ diff --git a/src/google/protobuf/util/field_comparator_test.cc b/src/google/protobuf/util/field_comparator_test.cc new file mode 100644 index 00000000..748c7d11 --- /dev/null +++ b/src/google/protobuf/util/field_comparator_test.cc @@ -0,0 +1,483 @@ +// 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. + +// Author: ksroka@google.com (Krzysztof Sroka) + +#include <google/protobuf/util/field_comparator.h> + +#include <google/protobuf/unittest.pb.h> +#include <google/protobuf/descriptor.h> +#include <gtest/gtest.h> +#include <google/protobuf/stubs/mathutil.h> + +namespace google { +namespace protobuf { +namespace util { +namespace { + +using protobuf_unittest::TestAllTypes; + +class DefaultFieldComparatorTest : public ::testing::Test { + protected: + void SetUp() { + descriptor_ = TestAllTypes::descriptor(); + } + + const Descriptor* descriptor_; + DefaultFieldComparator comparator_; + TestAllTypes message_1_; + TestAllTypes message_2_; +}; + +TEST_F(DefaultFieldComparatorTest, RecursesIntoGroup) { + const FieldDescriptor* field = + descriptor_->FindFieldByName("optionalgroup"); + EXPECT_EQ(FieldComparator::RECURSE, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, RecursesIntoNestedMessage) { + const FieldDescriptor* field = + descriptor_->FindFieldByName("optional_nested_message"); + EXPECT_EQ(FieldComparator::RECURSE, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, RecursesIntoForeignMessage) { + const FieldDescriptor* field = + descriptor_->FindFieldByName("optional_foreign_message"); + EXPECT_EQ(FieldComparator::RECURSE, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, Int32Comparison) { + const FieldDescriptor* field = descriptor_->FindFieldByName("optional_int32"); + message_1_.set_optional_int32(1); + message_2_.set_optional_int32(1); + + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); + + message_2_.set_optional_int32(-1); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, Int64Comparison) { + const FieldDescriptor* field = descriptor_->FindFieldByName("optional_int64"); + message_1_.set_optional_int64(1L); + message_2_.set_optional_int64(1L); + + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); + + message_2_.set_optional_int64(-1L); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, UInt32Comparison) { + const FieldDescriptor* field = + descriptor_->FindFieldByName("optional_uint32"); + message_1_.set_optional_uint32(1); + message_2_.set_optional_uint32(1); + + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); + + message_2_.set_optional_uint32(2); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, UInt64Comparison) { + const FieldDescriptor* field = + descriptor_->FindFieldByName("optional_uint64"); + message_1_.set_optional_uint64(1L); + message_2_.set_optional_uint64(1L); + + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); + + message_2_.set_optional_uint64(2L); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, BooleanComparison) { + const FieldDescriptor* field = + descriptor_->FindFieldByName("optional_bool"); + message_1_.set_optional_bool(true); + message_2_.set_optional_bool(true); + + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); + + message_2_.set_optional_bool(false); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, EnumComparison) { + const FieldDescriptor* field = + descriptor_->FindFieldByName("optional_nested_enum"); + message_1_.set_optional_nested_enum(TestAllTypes::BAR); + message_2_.set_optional_nested_enum(TestAllTypes::BAR); + + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); + + message_2_.set_optional_nested_enum(TestAllTypes::BAZ); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, StringComparison) { + const FieldDescriptor* field = + descriptor_->FindFieldByName("optional_string"); + message_1_.set_optional_string("foo"); + message_2_.set_optional_string("foo"); + + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); + + message_2_.set_optional_string("bar"); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonExact) { + const FieldDescriptor* field_float = + descriptor_->FindFieldByName("optional_float"); + const FieldDescriptor* field_double = + descriptor_->FindFieldByName("optional_double"); + + message_1_.set_optional_float(0.1f); + message_2_.set_optional_float(0.1f); + message_1_.set_optional_double(0.1); + message_2_.set_optional_double(0.1); + + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + message_2_.set_optional_float(0.2f); + message_2_.set_optional_double(0.2); + + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonApproximate) { + const FieldDescriptor* field_float = + descriptor_->FindFieldByName("optional_float"); + const FieldDescriptor* field_double = + descriptor_->FindFieldByName("optional_double"); + + message_1_.set_optional_float(2.300005f); + message_2_.set_optional_float(2.300006f); + message_1_.set_optional_double(2.3000000000000003); + message_2_.set_optional_double(2.3000000000000007); + + // Approximate comparison depends on MathUtil, so we assert on MathUtil + // results first to check if that's where the failure was introduced. + ASSERT_NE(message_1_.optional_float(), message_2_.optional_float()); + ASSERT_NE(message_1_.optional_double(), message_2_.optional_double()); + ASSERT_TRUE(MathUtil::AlmostEquals(message_1_.optional_float(), + message_2_.optional_float())); + ASSERT_TRUE(MathUtil::AlmostEquals(message_1_.optional_double(), + message_2_.optional_double())); + + // DefaultFieldComparator's default float comparison mode is EXACT. + ASSERT_EQ(DefaultFieldComparator::EXACT, comparator_.float_comparison()); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE); + + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonTreatNaNsAsEqual) { + const FieldDescriptor* field_float = + descriptor_->FindFieldByName("optional_float"); + const FieldDescriptor* field_double = + descriptor_->FindFieldByName("optional_double"); + + message_1_.set_optional_float(MathLimits<float>::kNaN); + message_2_.set_optional_float(MathLimits<float>::kNaN); + message_1_.set_optional_double(MathLimits<double>::kNaN); + message_2_.set_optional_double(MathLimits<double>::kNaN); + + // DefaultFieldComparator's default float comparison mode is EXACT with + // treating NaNs as different. + ASSERT_EQ(DefaultFieldComparator::EXACT, comparator_.float_comparison()); + ASSERT_EQ(false, comparator_.treat_nan_as_equal()); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + comparator_.set_treat_nan_as_equal(true); + ASSERT_EQ(true, comparator_.treat_nan_as_equal()); + comparator_.set_float_comparison(DefaultFieldComparator::EXACT); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, + FloatingPointComparisonWithinFractionOrMargin) { + const FieldDescriptor* field_float = + descriptor_->FindFieldByName("optional_float"); + const FieldDescriptor* field_double = + descriptor_->FindFieldByName("optional_double"); + + message_1_.set_optional_float(100.0f); + message_2_.set_optional_float(109.9f); + message_1_.set_optional_double(100.0); + message_2_.set_optional_double(109.9); + + comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // Should fail since the fraction is too low. + comparator_.SetFractionAndMargin(field_float, 0.01, 0.0); + comparator_.SetFractionAndMargin(field_double, 0.01, 0.0); + + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // Should fail since the margin is too low. + comparator_.SetFractionAndMargin(field_float, 0.0, 9.0); + comparator_.SetFractionAndMargin(field_double, 0.0, 9.0); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // Should succeed since the fraction is high enough. + comparator_.SetFractionAndMargin(field_float, 0.2, 0.0); + comparator_.SetFractionAndMargin(field_double, 0.2, 0.0); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // Should succeed since the margin is high enough. + comparator_.SetFractionAndMargin(field_float, 0.0, 10.0); + comparator_.SetFractionAndMargin(field_double, 0.0, 10.0); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // Setting values for one of the fields should not affect the other. + comparator_.SetFractionAndMargin(field_double, 0.0, 0.0); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // +inf should be equal even though they are not technically within margin or + // fraction. + message_1_.set_optional_float(numeric_limits<float>::infinity()); + message_2_.set_optional_float(numeric_limits<float>::infinity()); + message_1_.set_optional_double(numeric_limits<double>::infinity()); + message_2_.set_optional_double(numeric_limits<double>::infinity()); + comparator_.SetFractionAndMargin(field_float, 0.0, 0.0); + comparator_.SetFractionAndMargin(field_double, 0.0, 0.0); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // -inf should be equal even though they are not technically within margin or + // fraction. + message_1_.set_optional_float(-numeric_limits<float>::infinity()); + message_2_.set_optional_float(-numeric_limits<float>::infinity()); + message_1_.set_optional_double(-numeric_limits<double>::infinity()); + message_2_.set_optional_double(-numeric_limits<double>::infinity()); + comparator_.SetFractionAndMargin(field_float, 0.0, 0.0); + comparator_.SetFractionAndMargin(field_double, 0.0, 0.0); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, + FloatingPointComparisonWithinDefaultFractionOrMargin) { + const FieldDescriptor* field_float = + descriptor_->FindFieldByName("optional_float"); + const FieldDescriptor* field_double = + descriptor_->FindFieldByName("optional_double"); + + message_1_.set_optional_float(100.0f); + message_2_.set_optional_float(109.9f); + message_1_.set_optional_double(100.0); + message_2_.set_optional_double(109.9); + + comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // Set default fraction and margin. + comparator_.SetDefaultFractionAndMargin(0.01, 0.0); + + // Float comparisons should fail since the fraction is too low. + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // Set field-specific fraction and margin for one field (field_float) but not + // the other (field_double) + comparator_.SetFractionAndMargin(field_float, 0.2, 0.0); + + // The field with the override should succeed, since its field-specific + // fraction is high enough. + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + // The field with no override should fail, since the default fraction is too + // low + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // Set the default fraction and margin high enough so that fields that use + // the default should succeed + comparator_.SetDefaultFractionAndMargin(0.2, 0.0); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // The field with an override should still be OK + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + + // Set fraction and margin for the field with an override to be too low + comparator_.SetFractionAndMargin(field_float, 0.01, 0.0); + + // Now our default is high enough but field_float's override is too low. + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); +} + +// Simple test checking whether we compare values at correct indices. +TEST_F(DefaultFieldComparatorTest, RepeatedFieldComparison) { + const FieldDescriptor* field = + descriptor_->FindFieldByName("repeated_string"); + + message_1_.add_repeated_string("foo"); + message_1_.add_repeated_string("bar"); + message_2_.add_repeated_string("bar"); + message_2_.add_repeated_string("baz"); + + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, field, 0, 0, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, field, 1, 1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, field, 1, 0, NULL)); +} + +} // namespace util +} // namespace protobuf +} // namespace +} // namespace google diff --git a/src/google/protobuf/util/internal/constants.h b/src/google/protobuf/util/internal/constants.h new file mode 100644 index 00000000..0cb8f6e1 --- /dev/null +++ b/src/google/protobuf/util/internal/constants.h @@ -0,0 +1,93 @@ +// 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_UTIL_CONVERTER_CONSTANTS_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__ + +#include <google/protobuf/stubs/common.h> + +// This file contains constants used by //net/proto2/util/converter. + +namespace google { +namespace protobuf { +namespace util { +namespace converter { +// Prefix for type URLs. +const char kTypeServiceBaseUrl[] = "type.googleapis.com"; + +// Format string for RFC3339 timestamp formatting. +const char kRfc3339TimeFormat[] = "%Y-%m-%dT%H:%M:%S"; + +// Minimum seconds allowed in a google.protobuf.TimeStamp or Duration value. +const int64 kMinSeconds = -315576000000; + +// Maximum seconds allowed in a google.protobuf.TimeStamp or Duration value. +const int64 kMaxSeconds = 315576000000; + +// Nano seconds in a second. +const int32 kNanosPerSecond = 1000000000; + +// Type url representing NULL values in google.protobuf.Struct type. +const char kStructNullValueTypeUrl[] = + "type.googleapis.com/google.protobuf.NullValue"; + +// Type string for google.protobuf.Struct +const char kStructType[] = "google.protobuf.Struct"; + +// Type string for struct.proto's google.protobuf.Value value type. +const char kStructValueType[] = "google.protobuf.Value"; + +// Type string for struct.proto's google.protobuf.ListValue value type. +const char kStructListValueType[] = "google.protobuf.ListValue"; + +// Type string for google.protobuf.Timestamp +const char kTimestampType[] = "google.protobuf.Timestamp"; + +// Type string for google.protobuf.Duration +const char kDurationType[] = "google.protobuf.Duration"; + +// Type URL for struct value type google.protobuf.Value +const char kStructValueTypeUrl[] = "type.googleapis.com/google.protobuf.Value"; + +// Type URL for struct value type google.protobuf.Value +const char kStructTypeUrl[] = "type.googleapis.com/google.protobuf.Struct"; + +// Type string for google.protobuf.Any +const char kAnyType[] = "google.protobuf.Any"; + +// The type URL of google.protobuf.FieldMask; +const char kFieldMaskTypeUrl[] = + "type.googleapis.com/google.protobuf.FieldMask"; + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__ diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc new file mode 100644 index 00000000..72b737e9 --- /dev/null +++ b/src/google/protobuf/util/internal/datapiece.cc @@ -0,0 +1,285 @@ +// 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/util/internal/datapiece.h> + +#include <google/protobuf/struct.pb.h> +#include <google/protobuf/type.pb.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/util/internal/utility.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/mathutil.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +using google::protobuf::EnumDescriptor; +using google::protobuf::EnumValueDescriptor; +; +; +using util::error::Code; +using util::Status; +using util::StatusOr; + +namespace { + +inline Status InvalidArgument(StringPiece value_str) { + return Status(util::error::INVALID_ARGUMENT, value_str); +} + +// For general conversion between +// int32, int64, uint32, uint64, double and float +// except conversion between double and float. +template <typename To, typename From> +StatusOr<To> NumberConvertAndCheck(From before) { + if (::google::protobuf::internal::is_same<From, To>::value) return before; + To after = static_cast<To>(before); + if (after == before && + MathUtil::Sign<From>(before) == MathUtil::Sign<To>(after)) { + return after; + } else { + return InvalidArgument(::google::protobuf::internal::is_integral<From>::value + ? ValueAsString(before) + : ::google::protobuf::internal::is_same<From, double>::value + ? DoubleAsString(before) + : FloatAsString(before)); + } +} + +// For conversion between double and float only. +template <typename To, typename From> +StatusOr<To> FloatingPointConvertAndCheck(From before) { + if (isnan(before)) return std::numeric_limits<To>::quiet_NaN(); + + To after = static_cast<To>(before); + if (MathUtil::AlmostEquals<To>(after, before)) { + return after; + } else { + return InvalidArgument(::google::protobuf::internal::is_same<From, double>::value + ? DoubleAsString(before) + : FloatAsString(before)); + } +} + +} // namespace + +StatusOr<int32> DataPiece::ToInt32() const { + if (type_ == TYPE_STRING) { + return StringToNumber<int32>(safe_strto32); + } + return GenericConvert<int32>(); +} + +StatusOr<uint32> DataPiece::ToUint32() const { + if (type_ == TYPE_STRING) { + return StringToNumber<uint32>(safe_strtou32); + } + return GenericConvert<uint32>(); +} + +StatusOr<int64> DataPiece::ToInt64() const { + if (type_ == TYPE_STRING) { + return StringToNumber<int64>(safe_strto64); + } + return GenericConvert<int64>(); +} + +StatusOr<uint64> DataPiece::ToUint64() const { + if (type_ == TYPE_STRING) { + return StringToNumber<uint64>(safe_strtou64); + } + return GenericConvert<uint64>(); +} + +StatusOr<double> DataPiece::ToDouble() const { + if (type_ == TYPE_FLOAT) { + return FloatingPointConvertAndCheck<double, float>(float_); + } + if (type_ == TYPE_STRING) { + if (str_ == "Infinity") return std::numeric_limits<double>::infinity(); + if (str_ == "-Infinity") return -std::numeric_limits<double>::infinity(); + if (str_ == "NaN") return std::numeric_limits<double>::quiet_NaN(); + return StringToNumber<double>(safe_strtod); + } + return GenericConvert<double>(); +} + +StatusOr<float> DataPiece::ToFloat() const { + if (type_ == TYPE_DOUBLE) { + return FloatingPointConvertAndCheck<float, double>(double_); + } + if (type_ == TYPE_STRING) { + if (str_ == "Infinity") return std::numeric_limits<float>::infinity(); + if (str_ == "-Infinity") return -std::numeric_limits<float>::infinity(); + if (str_ == "NaN") return std::numeric_limits<float>::quiet_NaN(); + // SafeStrToFloat() is used instead of safe_strtof() because the later + // does not fail on inputs like SimpleDtoa(DBL_MAX). + return StringToNumber<float>(SafeStrToFloat); + } + return GenericConvert<float>(); +} + +StatusOr<bool> DataPiece::ToBool() const { + switch (type_) { + case TYPE_BOOL: + return bool_; + case TYPE_STRING: + return StringToNumber<bool>(safe_strtob); + default: + return InvalidArgument( + ValueAsStringOrDefault("Wrong type. Cannot convert to Bool.")); + } +} + +StatusOr<string> DataPiece::ToString() const { + switch (type_) { + case TYPE_STRING: + return str_.ToString(); + case TYPE_BYTES: { + string base64; + WebSafeBase64Escape(str_, &base64); + return base64; + } + default: + return InvalidArgument( + ValueAsStringOrDefault("Cannot convert to string.")); + } +} + +string DataPiece::ValueAsStringOrDefault(StringPiece default_string) const { + switch (type_) { + case TYPE_INT32: + return SimpleItoa(i32_); + case TYPE_INT64: + return SimpleItoa(i64_); + case TYPE_UINT32: + return SimpleItoa(u32_); + case TYPE_UINT64: + return SimpleItoa(u64_); + case TYPE_DOUBLE: + return DoubleAsString(double_); + case TYPE_FLOAT: + return FloatAsString(float_); + case TYPE_BOOL: + return SimpleBtoa(bool_); + case TYPE_STRING: + return StrCat("\"", str_.ToString(), "\""); + case TYPE_BYTES: { + string base64; + WebSafeBase64Escape(str_, &base64); + return StrCat("\"", base64, "\""); + } + case TYPE_NULL: + return "null"; + default: + return default_string.ToString(); + } +} + +StatusOr<string> DataPiece::ToBytes() const { + if (type_ == TYPE_BYTES) return str_.ToString(); + if (type_ == TYPE_STRING) { + string decoded; + if (!WebSafeBase64Unescape(str_, &decoded)) { + if (!Base64Unescape(str_, &decoded)) { + return InvalidArgument( + ValueAsStringOrDefault("Invalid data in input.")); + } + } + return decoded; + } else { + return InvalidArgument(ValueAsStringOrDefault( + "Wrong type. Only String or Bytes can be converted to Bytes.")); + } +} + +StatusOr<int> DataPiece::ToEnum(const google::protobuf::Enum* enum_type) const { + if (type_ == TYPE_NULL) return google::protobuf::NULL_VALUE; + + if (type_ == TYPE_STRING) { + // First try the given value as a name. + string enum_name = str_.ToString(); + const google::protobuf::EnumValue* value = + FindEnumValueByNameOrNull(enum_type, enum_name); + if (value != NULL) return value->number(); + // Next try a normalized name. + for (string::iterator it = enum_name.begin(); it != enum_name.end(); ++it) { + *it = *it == '-' ? '_' : ascii_toupper(*it); + } + value = FindEnumValueByNameOrNull(enum_type, enum_name); + if (value != NULL) return value->number(); + } else { + StatusOr<int32> value = ToInt32(); + if (value.ok()) { + if (const google::protobuf::EnumValue* enum_value = + FindEnumValueByNumberOrNull(enum_type, value.ValueOrDie())) { + return enum_value->number(); + } + } + } + return InvalidArgument( + ValueAsStringOrDefault("Cannot find enum with given value.")); +} + +template <typename To> +StatusOr<To> DataPiece::GenericConvert() const { + switch (type_) { + case TYPE_INT32: + return NumberConvertAndCheck<To, int32>(i32_); + case TYPE_INT64: + return NumberConvertAndCheck<To, int64>(i64_); + case TYPE_UINT32: + return NumberConvertAndCheck<To, uint32>(u32_); + case TYPE_UINT64: + return NumberConvertAndCheck<To, uint64>(u64_); + case TYPE_DOUBLE: + return NumberConvertAndCheck<To, double>(double_); + case TYPE_FLOAT: + return NumberConvertAndCheck<To, float>(float_); + default: // TYPE_ENUM, TYPE_STRING, TYPE_CORD, TYPE_BOOL + return InvalidArgument(ValueAsStringOrDefault( + "Wrong type. Bool, Enum, String and Cord not supported in " + "GenericConvert.")); + } +} + +template <typename To> +StatusOr<To> DataPiece::StringToNumber(bool (*func)(StringPiece, To*)) const { + To result; + if (func(str_, &result)) return result; + return InvalidArgument(StrCat("\"", str_.ToString(), "\"")); +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/datapiece.h b/src/google/protobuf/util/internal/datapiece.h new file mode 100644 index 00000000..30947252 --- /dev/null +++ b/src/google/protobuf/util/internal/datapiece.h @@ -0,0 +1,212 @@ +// 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_UTIL_CONVERTER_DATAPIECE_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_DATAPIECE_H__ + +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/stringpiece.h> +#include <google/protobuf/stubs/statusor.h> + + +namespace google { +namespace protobuf { +class Enum; +} // namespace protobuf + + +namespace protobuf { +namespace util { +namespace converter { + +// Container for a single piece of data together with its data type. +// +// For primitive types (int32, int64, uint32, uint64, double, float, bool), +// the data is stored by value. +// +// For string, a StringPiece is stored. For Cord, a pointer to Cord is stored. +// Just like StringPiece, the DataPiece class does not own the storage for +// the actual string or Cord, so it is the user's responsiblity to guarantee +// that the underlying storage is still valid when the DataPiece is accessed. +class LIBPROTOBUF_EXPORT DataPiece { + public: + // Identifies data type of the value. + // These are the types supported by DataPiece. + enum Type { + TYPE_INT32 = 1, + TYPE_INT64 = 2, + TYPE_UINT32 = 3, + TYPE_UINT64 = 4, + TYPE_DOUBLE = 5, + TYPE_FLOAT = 6, + TYPE_BOOL = 7, + TYPE_ENUM = 8, + TYPE_STRING = 9, + TYPE_BYTES = 10, + TYPE_NULL = 11, // explicit NULL type + }; + + // Constructors and Destructor + explicit DataPiece(const int32 value) : type_(TYPE_INT32), i32_(value) {} + explicit DataPiece(const int64 value) : type_(TYPE_INT64), i64_(value) {} + explicit DataPiece(const uint32 value) : type_(TYPE_UINT32), u32_(value) {} + explicit DataPiece(const uint64 value) : type_(TYPE_UINT64), u64_(value) {} + explicit DataPiece(const double value) : type_(TYPE_DOUBLE), double_(value) {} + explicit DataPiece(const float value) : type_(TYPE_FLOAT), float_(value) {} + explicit DataPiece(const bool value) : type_(TYPE_BOOL), bool_(value) {} + explicit DataPiece(StringPiece value) + : type_(TYPE_STRING), + str_(StringPiecePod::CreateFromStringPiece(value)) {} + // Constructor for bytes. The second parameter is not used. + explicit DataPiece(StringPiece value, bool dummy) + : type_(TYPE_BYTES), str_(StringPiecePod::CreateFromStringPiece(value)) {} + DataPiece(const DataPiece& r) : type_(r.type_), str_(r.str_) {} + DataPiece& operator=(const DataPiece& x) { + type_ = x.type_; + str_ = x.str_; + return *this; + } + + static DataPiece NullData() { return DataPiece(TYPE_NULL, 0); } + + virtual ~DataPiece() {} + + // Accessors + Type type() const { return type_; } + + StringPiece str() const { + GOOGLE_LOG_IF(DFATAL, type_ != TYPE_STRING) << "Not a string type."; + return str_; + } + + + // Parses, casts or converts the value stored in the DataPiece into an int32. + util::StatusOr<int32> ToInt32() const; + + // Parses, casts or converts the value stored in the DataPiece into a uint32. + util::StatusOr<uint32> ToUint32() const; + + // Parses, casts or converts the value stored in the DataPiece into an int64. + util::StatusOr<int64> ToInt64() const; + + // Parses, casts or converts the value stored in the DataPiece into a uint64. + util::StatusOr<uint64> ToUint64() const; + + // Parses, casts or converts the value stored in the DataPiece into a double. + util::StatusOr<double> ToDouble() const; + + // Parses, casts or converts the value stored in the DataPiece into a float. + util::StatusOr<float> ToFloat() const; + + // Parses, casts or converts the value stored in the DataPiece into a bool. + util::StatusOr<bool> ToBool() const; + + // Parses, casts or converts the value stored in the DataPiece into a string. + util::StatusOr<string> ToString() const; + + // Tries to convert the value contained in this datapiece to string. If the + // conversion fails, it returns the default_string. + string ValueAsStringOrDefault(StringPiece default_string) const; + + util::StatusOr<string> ToBytes() const; + + // Converts a value into protocol buffer enum number. If the value is a + // string, first attempts conversion by name, trying names as follows: + // 1) the directly provided string value. + // 2) the value upper-cased and replacing '-' by '_' + // If the value is not a string, attempts to convert to a 32-bit integer. + // If none of these succeeds, returns a conversion error status. + util::StatusOr<int> ToEnum(const google::protobuf::Enum* enum_type) const; + + private: + // Disallow implicit constructor. + DataPiece(); + + // Helper to create NULL or ENUM types. + DataPiece(Type type, int32 val) : type_(type), i32_(val) {} + + // For numeric conversion between + // int32, int64, uint32, uint64, double, float and bool + template <typename To> + util::StatusOr<To> GenericConvert() const; + + // For conversion from string to + // int32, int64, uint32, uint64, double, float and bool + template <typename To> + util::StatusOr<To> StringToNumber(bool (*func)(StringPiece, To*)) const; + + // Data type for this piece of data. + Type type_; + + // StringPiece is not a POD and can not be used in an union (pre C++11). We + // need a POD version of it. + struct StringPiecePod { + const char* data; + int size; + + // Create from a StringPiece. + static StringPiecePod CreateFromStringPiece(StringPiece str) { + StringPiecePod pod; + pod.data = str.data(); + pod.size = str.size(); + return pod; + } + + // Cast to StringPiece. + operator StringPiece() const { return StringPiece(data, size); } + + bool operator==(const char* value) const { + return StringPiece(data, size) == StringPiece(value); + } + + string ToString() const { return string(data, size); } + }; + + // Stored piece of data. + union { + const int32 i32_; + const int64 i64_; + const uint32 u32_; + const uint64 u64_; + const double double_; + const float float_; + const bool bool_; + StringPiecePod str_; + }; +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_DATAPIECE_H__ diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc new file mode 100644 index 00000000..267e2cd3 --- /dev/null +++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc @@ -0,0 +1,515 @@ +// 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/util/internal/default_value_objectwriter.h> + +#include <google/protobuf/stubs/hash.h> + +#include <google/protobuf/util/internal/constants.h> +#include <google/protobuf/stubs/map_util.h> + +namespace google { +namespace protobuf { +namespace util { +using util::Status; +using util::StatusOr; +namespace converter { + +DefaultValueObjectWriter::DefaultValueObjectWriter( + TypeResolver* type_resolver, const google::protobuf::Type& type, + ObjectWriter* ow) + : typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), + type_(type), + disable_normalize_(false), + current_(NULL), + root_(NULL), + ow_(ow) {} + +DefaultValueObjectWriter::~DefaultValueObjectWriter() { + for (int i = 0; i < string_values_.size(); ++i) { + delete string_values_[i]; + } +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBool(StringPiece name, + bool value) { + if (current_ == NULL) { + ow_->RenderBool(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt32( + StringPiece name, int32 value) { + if (current_ == NULL) { + ow_->RenderInt32(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint32( + StringPiece name, uint32 value) { + if (current_ == NULL) { + ow_->RenderUint32(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt64( + StringPiece name, int64 value) { + if (current_ == NULL) { + ow_->RenderInt64(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint64( + StringPiece name, uint64 value) { + if (current_ == NULL) { + ow_->RenderUint64(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderDouble( + StringPiece name, double value) { + if (current_ == NULL) { + ow_->RenderDouble(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderFloat( + StringPiece name, float value) { + if (current_ == NULL) { + ow_->RenderBool(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderString( + StringPiece name, StringPiece value) { + if (current_ == NULL) { + ow_->RenderString(name, value); + } else { + // Since StringPiece is essentially a pointer, takes a copy of "value" to + // avoid ownership issues. + string_values_.push_back(new string(value.ToString())); + RenderDataPiece(name, DataPiece(*string_values_.back())); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBytes( + StringPiece name, StringPiece value) { + if (current_ == NULL) { + ow_->RenderBytes(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderNull( + StringPiece name) { + if (current_ == NULL) { + ow_->RenderNull(name); + } else { + RenderDataPiece(name, DataPiece::NullData()); + } + return this; +} + +DefaultValueObjectWriter* +DefaultValueObjectWriter::DisableCaseNormalizationForNextKey() { + disable_normalize_ = true; + return this; +} + +DefaultValueObjectWriter::Node::Node(const string& name, + const google::protobuf::Type* type, + NodeKind kind, const DataPiece& data, + bool is_placeholder) + : name_(name), + type_(type), + kind_(kind), + disable_normalize_(false), + is_any_(false), + data_(data), + is_placeholder_(is_placeholder) {} + +DefaultValueObjectWriter::Node* DefaultValueObjectWriter::Node::FindChild( + StringPiece name) { + if (name.empty() || kind_ != OBJECT) { + return NULL; + } + for (int i = 0; i < children_.size(); ++i) { + Node* child = children_[i]; + if (child->name() == name) { + return child; + } + } + return NULL; +} + +void DefaultValueObjectWriter::Node::WriteTo(ObjectWriter* ow) { + if (disable_normalize_) { + ow->DisableCaseNormalizationForNextKey(); + } + if (kind_ == PRIMITIVE) { + ObjectWriter::RenderDataPieceTo(data_, name_, ow); + return; + } + if (is_placeholder_) { + // If is_placeholder_ = true, we didn't see this node in the response, so + // skip output. + return; + } + if (kind_ == LIST) { + ow->StartList(name_); + } else { + ow->StartObject(name_); + } + for (int i = 0; i < children_.size(); ++i) { + Node* child = children_[i]; + child->WriteTo(ow); + } + if (kind_ == LIST) { + ow->EndList(); + } else { + ow->EndObject(); + } +} + +const google::protobuf::Type* DefaultValueObjectWriter::Node::GetMapValueType( + const google::protobuf::Type& found_type, TypeInfo* typeinfo) { + // If this field is a map, we should use the type of its "Value" as + // the type of the child node. + for (int i = 0; i < found_type.fields_size(); ++i) { + const google::protobuf::Field& sub_field = found_type.fields(i); + if (sub_field.number() != 2) { + continue; + } + if (sub_field.kind() != google::protobuf::Field_Kind_TYPE_MESSAGE) { + // This map's value type is not a message type. We don't need to + // get the field_type in this case. + break; + } + util::StatusOr<const google::protobuf::Type*> sub_type = + typeinfo->ResolveTypeUrl(sub_field.type_url()); + if (!sub_type.ok()) { + GOOGLE_LOG(WARNING) << "Cannot resolve type '" << sub_field.type_url() << "'."; + } else { + return sub_type.ValueOrDie(); + } + break; + } + return NULL; +} + +void DefaultValueObjectWriter::Node::PopulateChildren(TypeInfo* typeinfo) { + // Ignores well known types that don't require automatically populating their + // primitive children. For type "Any", we only populate its children when the + // "@type" field is set. + // TODO(tsun): remove "kStructValueType" from the list. It's being checked + // now because of a bug in the tool-chain that causes the "oneof_index" + // of kStructValueType to not be set correctly. + if (type_ == NULL || type_->name() == kAnyType || + type_->name() == kStructType || type_->name() == kTimestampType || + type_->name() == kDurationType || type_->name() == kStructValueType) { + return; + } + std::vector<Node*> new_children; + hash_map<string, int> orig_children_map; + + // Creates a map of child nodes to speed up lookup. + for (int i = 0; i < children_.size(); ++i) { + InsertIfNotPresent(&orig_children_map, children_[i]->name_, i); + } + + for (int i = 0; i < type_->fields_size(); ++i) { + const google::protobuf::Field& field = type_->fields(i); + hash_map<string, int>::iterator found = + orig_children_map.find(field.name()); + // If the child field has already been set, we just add it to the new list + // of children. + if (found != orig_children_map.end()) { + new_children.push_back(children_[found->second]); + children_[found->second] = NULL; + continue; + } + + const google::protobuf::Type* field_type = NULL; + bool is_map = false; + NodeKind kind = PRIMITIVE; + + if (field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) { + kind = OBJECT; + util::StatusOr<const google::protobuf::Type*> found_result = + typeinfo->ResolveTypeUrl(field.type_url()); + if (!found_result.ok()) { + // "field" is of an unknown type. + GOOGLE_LOG(WARNING) << "Cannot resolve type '" << field.type_url() << "'."; + } else { + const google::protobuf::Type* found_type = found_result.ValueOrDie(); + is_map = IsMap(field, *found_type); + + if (!is_map) { + field_type = found_type; + } else { + // If this field is a map, we should use the type of its "Value" as + // the type of the child node. + field_type = GetMapValueType(*found_type, typeinfo); + kind = MAP; + } + } + } + if (!is_map && + field.cardinality() == + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) { + kind = LIST; + } + // If the child field is of primitive type, sets its data to the default + // value of its type. + // If oneof_index() != 0, the child field is part of a "oneof", which means + // the child field is optional and we shouldn't populate its default value. + google::protobuf::scoped_ptr<Node> child( + new Node(field.name(), field_type, kind, + ((kind == PRIMITIVE && field.oneof_index() == 0) + ? CreateDefaultDataPieceForField(field) + : DataPiece::NullData()), + true)); + new_children.push_back(child.release()); + } + // Adds all leftover nodes in children_ to the beginning of new_child. + for (int i = 0; i < children_.size(); ++i) { + if (children_[i] == NULL) { + continue; + } + new_children.insert(new_children.begin(), children_[i]); + children_[i] = NULL; + } + children_.swap(new_children); +} + +void DefaultValueObjectWriter::MaybePopulateChildrenOfAny(Node* node) { + // If this is an "Any" node with "@type" already given and no other children + // have been added, populates its children. + if (node != NULL && node->is_any() && node->type() != NULL && + node->type()->name() != kAnyType && node->number_of_children() == 1) { + node->PopulateChildren(typeinfo_.get()); + } +} + +DataPiece DefaultValueObjectWriter::CreateDefaultDataPieceForField( + const google::protobuf::Field& field) { + switch (field.kind()) { + case google::protobuf::Field_Kind_TYPE_DOUBLE: { + return DataPiece(static_cast<double>(0)); + } + case google::protobuf::Field_Kind_TYPE_FLOAT: { + return DataPiece(static_cast<float>(0)); + } + case google::protobuf::Field_Kind_TYPE_INT64: + case google::protobuf::Field_Kind_TYPE_SINT64: + case google::protobuf::Field_Kind_TYPE_SFIXED64: { + return DataPiece(static_cast<int64>(0)); + } + case google::protobuf::Field_Kind_TYPE_UINT64: + case google::protobuf::Field_Kind_TYPE_FIXED64: { + return DataPiece(static_cast<uint64>(0)); + } + case google::protobuf::Field_Kind_TYPE_INT32: + case google::protobuf::Field_Kind_TYPE_SINT32: + case google::protobuf::Field_Kind_TYPE_SFIXED32: { + return DataPiece(static_cast<int32>(0)); + } + case google::protobuf::Field_Kind_TYPE_BOOL: { + return DataPiece(false); + } + case google::protobuf::Field_Kind_TYPE_STRING: { + return DataPiece(string()); + } + case google::protobuf::Field_Kind_TYPE_BYTES: { + return DataPiece("", false); + } + case google::protobuf::Field_Kind_TYPE_UINT32: + case google::protobuf::Field_Kind_TYPE_FIXED32: { + return DataPiece(static_cast<uint32>(0)); + } + default: { return DataPiece::NullData(); } + } +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject( + StringPiece name) { + if (current_ == NULL) { + root_.reset(new Node(name.ToString(), &type_, OBJECT, DataPiece::NullData(), + false)); + root_->set_disable_normalize(GetAndResetDisableNormalize()); + root_->PopulateChildren(typeinfo_.get()); + current_ = root_.get(); + return this; + } + MaybePopulateChildrenOfAny(current_); + Node* child = current_->FindChild(name); + if (current_->kind() == LIST || current_->kind() == MAP || child == NULL) { + // If current_ is a list or a map node, we should create a new child and use + // the type of current_ as the type of the new child. + google::protobuf::scoped_ptr<Node> node(new Node( + name.ToString(), ((current_->kind() == LIST || current_->kind() == MAP) + ? current_->type() + : NULL), + OBJECT, DataPiece::NullData(), false)); + child = node.get(); + current_->AddChild(node.release()); + } + + child->set_is_placeholder(false); + child->set_disable_normalize(GetAndResetDisableNormalize()); + if (child->kind() == OBJECT && child->number_of_children() == 0) { + child->PopulateChildren(typeinfo_.get()); + } + + stack_.push(current_); + current_ = child; + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::EndObject() { + if (stack_.empty()) { + // The root object ends here. Writes out the tree. + WriteRoot(); + return this; + } + current_ = stack_.top(); + stack_.pop(); + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::StartList( + StringPiece name) { + if (current_ == NULL) { + root_.reset( + new Node(name.ToString(), &type_, LIST, DataPiece::NullData(), false)); + root_->set_disable_normalize(GetAndResetDisableNormalize()); + current_ = root_.get(); + return this; + } + MaybePopulateChildrenOfAny(current_); + Node* child = current_->FindChild(name); + if (child == NULL || child->kind() != LIST) { + GOOGLE_LOG(WARNING) << "Cannot find field '" << name << "'."; + google::protobuf::scoped_ptr<Node> node( + new Node(name.ToString(), NULL, LIST, DataPiece::NullData(), false)); + child = node.get(); + current_->AddChild(node.release()); + } + child->set_is_placeholder(false); + child->set_disable_normalize(GetAndResetDisableNormalize()); + + stack_.push(current_); + current_ = child; + return this; +} + +void DefaultValueObjectWriter::WriteRoot() { + root_->WriteTo(ow_); + root_.reset(NULL); + current_ = NULL; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::EndList() { + if (stack_.empty()) { + WriteRoot(); + return this; + } + current_ = stack_.top(); + stack_.pop(); + return this; +} + +void DefaultValueObjectWriter::RenderDataPiece(StringPiece name, + const DataPiece& data) { + MaybePopulateChildrenOfAny(current_); + util::StatusOr<string> data_string = data.ToString(); + if (current_->type() != NULL && current_->type()->name() == kAnyType && + name == "@type" && data_string.ok()) { + const string& string_value = data_string.ValueOrDie(); + // If the type of current_ is "Any" and its "@type" field is being set here, + // sets the type of current_ to be the type specified by the "@type". + util::StatusOr<const google::protobuf::Type*> found_type = + typeinfo_->ResolveTypeUrl(string_value); + if (!found_type.ok()) { + GOOGLE_LOG(WARNING) << "Failed to resolve type '" << string_value << "'."; + } else { + current_->set_type(found_type.ValueOrDie()); + } + current_->set_is_any(true); + // If the "@type" field is placed after other fields, we should populate + // other children of primitive type now. Otherwise, we should wait until the + // first value field is rendered before we populate the children, because + // the "value" field of a Any message could be omitted. + if (current_->number_of_children() > 1 && current_->type() != NULL) { + current_->PopulateChildren(typeinfo_.get()); + } + } + Node* child = current_->FindChild(name); + if (child == NULL || child->kind() != PRIMITIVE) { + GOOGLE_LOG(WARNING) << "Cannot find primitive field '" << name << "'."; + // No children are found, creates a new child. + google::protobuf::scoped_ptr<Node> node( + new Node(name.ToString(), NULL, PRIMITIVE, data, false)); + child = node.get(); + current_->AddChild(node.release()); + } else { + child->set_data(data); + } + child->set_disable_normalize(GetAndResetDisableNormalize()); +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h new file mode 100644 index 00000000..759ba91b --- /dev/null +++ b/src/google/protobuf/util/internal/default_value_objectwriter.h @@ -0,0 +1,238 @@ +// 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_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__ + +#include <memory> +#ifndef _SHARED_PTR_H +#include <google/protobuf/stubs/shared_ptr.h> +#endif +#include <stack> +#include <vector> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/util/internal/type_info.h> +#include <google/protobuf/util/internal/datapiece.h> +#include <google/protobuf/util/internal/object_writer.h> +#include <google/protobuf/util/internal/utility.h> +#include <google/protobuf/util/type_resolver.h> +#include <google/protobuf/stubs/stringpiece.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// An ObjectWriter that renders non-repeated primitive fields of proto messages +// with their default values. DefaultValueObjectWriter holds objects, lists and +// fields it receives in a tree structure and writes them out to another +// ObjectWriter when EndObject() is called on the root object. It also writes +// out all non-repeated primitive fields that haven't been explicitly rendered +// with their default values (0 for numbers, "" for strings, etc). +class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { + public: + DefaultValueObjectWriter(TypeResolver* type_resolver, + const google::protobuf::Type& type, + ObjectWriter* ow); + + virtual ~DefaultValueObjectWriter(); + + // ObjectWriter methods. + virtual DefaultValueObjectWriter* StartObject(StringPiece name); + + virtual DefaultValueObjectWriter* EndObject(); + + virtual DefaultValueObjectWriter* StartList(StringPiece name); + + virtual DefaultValueObjectWriter* EndList(); + + virtual DefaultValueObjectWriter* RenderBool(StringPiece name, bool value); + + virtual DefaultValueObjectWriter* RenderInt32(StringPiece name, int32 value); + + virtual DefaultValueObjectWriter* RenderUint32(StringPiece name, + uint32 value); + + virtual DefaultValueObjectWriter* RenderInt64(StringPiece name, int64 value); + + virtual DefaultValueObjectWriter* RenderUint64(StringPiece name, + uint64 value); + + virtual DefaultValueObjectWriter* RenderDouble(StringPiece name, + double value); + + virtual DefaultValueObjectWriter* RenderFloat(StringPiece name, float value); + + virtual DefaultValueObjectWriter* RenderString(StringPiece name, + StringPiece value); + virtual DefaultValueObjectWriter* RenderBytes(StringPiece name, + StringPiece value); + + virtual DefaultValueObjectWriter* RenderNull(StringPiece name); + + virtual DefaultValueObjectWriter* DisableCaseNormalizationForNextKey(); + + private: + enum NodeKind { + PRIMITIVE = 0, + OBJECT = 1, + LIST = 2, + MAP = 3, + }; + + // "Node" represents a node in the tree that holds the input of + // DefaultValueObjectWriter. + class Node { + public: + Node(const string& name, const google::protobuf::Type* type, NodeKind kind, + const DataPiece& data, bool is_placeholder); + virtual ~Node() { + for (int i = 0; i < children_.size(); ++i) { + delete children_[i]; + } + } + + // Adds a child to this node. Takes ownership of this child. + void AddChild(Node* child) { children_.push_back(child); } + + // Finds the child given its name. + Node* FindChild(StringPiece name); + + // Populates children of this Node based on its type. If there are already + // children created, they will be merged to the result. Caller should pass + // in TypeInfo for looking up types of the children. + void PopulateChildren(TypeInfo* typeinfo); + + // If this node is a leaf (has data), writes the current node to the + // ObjectWriter; if not, then recursively writes the children to the + // ObjectWriter. + void WriteTo(ObjectWriter* ow); + + // Accessors + const string& name() const { return name_; } + + const google::protobuf::Type* type() { return type_; } + + void set_type(const google::protobuf::Type* type) { type_ = type; } + + NodeKind kind() { return kind_; } + + int number_of_children() { return children_.size(); } + + void set_data(const DataPiece& data) { data_ = data; } + + void set_disable_normalize(bool disable_normalize) { + disable_normalize_ = disable_normalize; + } + + bool is_any() { return is_any_; } + + void set_is_any(bool is_any) { is_any_ = is_any; } + + void set_is_placeholder(bool is_placeholder) { + is_placeholder_ = is_placeholder; + } + + private: + // Returns the Value Type of a map given the Type of the map entry and a + // TypeInfo instance. + const google::protobuf::Type* GetMapValueType( + const google::protobuf::Type& entry_type, TypeInfo* typeinfo); + + // The name of this node. + string name_; + // google::protobuf::Type of this node. Owned by TypeInfo. + const google::protobuf::Type* type_; + // The kind of this node. + NodeKind kind_; + // Whether to disable case normalization of the name. + bool disable_normalize_; + // Whether this is a node for "Any". + bool is_any_; + // The data of this node when it is a leaf node. + DataPiece data_; + // Children of this node. + std::vector<Node*> children_; + // Whether this node is a placeholder for an object or list automatically + // generated when creating the parent node. Should be set to false after + // the parent node's StartObject()/StartList() method is called with this + // node's name. + bool is_placeholder_; + }; + + // Populates children of "node" if it is an "any" Node and its real type has + // been given. + void MaybePopulateChildrenOfAny(Node* node); + + // Writes the root_ node to ow_ and resets the root_ and current_ pointer to + // NULL. + void WriteRoot(); + + // Creates a DataPiece containing the default value of the type of the field. + static DataPiece CreateDefaultDataPieceForField( + const google::protobuf::Field& field); + + // Returns disable_normalize_ and reset it to false. + bool GetAndResetDisableNormalize() { + return disable_normalize_ ? (disable_normalize_ = false, true) : false; + } + + // Adds or replaces the data_ of a primitive child node. + void RenderDataPiece(StringPiece name, const DataPiece& data); + + // Type information for all the types used in the descriptor. Used to find + // google::protobuf::Type of nested messages/enums. + google::protobuf::scoped_ptr<TypeInfo> typeinfo_; + // google::protobuf::Type of the root message type. + const google::protobuf::Type& type_; + // Holds copies of strings passed to RenderString. + vector<string*> string_values_; + + // Whether to disable case normalization of the next node. + bool disable_normalize_; + // The current Node. Owned by its parents. + Node* current_; + // The root Node. + google::protobuf::scoped_ptr<Node> root_; + // The stack to hold the path of Nodes from current_ to root_; + std::stack<Node*> stack_; + + ObjectWriter* ow_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultValueObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__ diff --git a/src/google/protobuf/util/internal/default_value_objectwriter_test.cc b/src/google/protobuf/util/internal/default_value_objectwriter_test.cc new file mode 100644 index 00000000..593c7105 --- /dev/null +++ b/src/google/protobuf/util/internal/default_value_objectwriter_test.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 <google/protobuf/util/internal/default_value_objectwriter.h> +#include <google/protobuf/util/internal/expecting_objectwriter.h> +#include <google/protobuf/util/internal/testdata/default_value_test.pb.h> +#include <google/protobuf/util/internal/type_info_test_helper.h> +#include <google/protobuf/util/internal/constants.h> +#include <gtest/gtest.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { +namespace testing { + +using google::protobuf::testing::DefaultValueTest; + +// Tests to cover some basic DefaultValueObjectWriter use cases. More tests are +// in the marshalling_test.cc and translator_integration_test.cc. +class DefaultValueObjectWriterTest + : public ::testing::TestWithParam<testing::TypeInfoSource> { + protected: + DefaultValueObjectWriterTest() + : helper_(GetParam()), mock_(), expects_(&mock_) { + helper_.ResetTypeInfo(DefaultValueTest::descriptor()); + testing_.reset(helper_.NewDefaultValueWriter( + string(kTypeServiceBaseUrl) + "/" + + DefaultValueTest::descriptor()->full_name(), + &mock_)); + } + + virtual ~DefaultValueObjectWriterTest() {} + + TypeInfoTestHelper helper_; + MockObjectWriter mock_; + ExpectingObjectWriter expects_; + google::protobuf::scoped_ptr<DefaultValueObjectWriter> testing_; +}; + +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + DefaultValueObjectWriterTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + +TEST_P(DefaultValueObjectWriterTest, Empty) { + // Set expectation + expects_.StartObject("") + ->RenderDouble("double_value", 0.0) + ->RenderFloat("float_value", 0.0) + ->RenderInt64("int64_value", 0) + ->RenderUint64("uint64_value", 0) + ->RenderInt32("int32_value", 0) + ->RenderUint32("uint32_value", 0) + ->RenderBool("bool_value", false) + ->RenderString("string_value", "") + ->RenderBytes("bytes_value", "") + ->EndObject(); + + // Actual testing + testing_->StartObject("")->EndObject(); +} + +TEST_P(DefaultValueObjectWriterTest, NonDefaultDouble) { + // Set expectation + expects_.StartObject("") + ->RenderDouble("double_value", 1.0) + ->RenderFloat("float_value", 0.0) + ->RenderInt64("int64_value", 0) + ->RenderUint64("uint64_value", 0) + ->RenderInt32("int32_value", 0) + ->RenderUint32("uint32_value", 0) + ->RenderBool("bool_value", false) + ->RenderString("string_value", "") + ->EndObject(); + + // Actual testing + testing_->StartObject("")->RenderDouble("double_value", 1.0)->EndObject(); +} + +TEST_P(DefaultValueObjectWriterTest, ShouldRetainUnknownField) { + // Set expectation + expects_.StartObject("") + ->RenderDouble("double_value", 1.0) + ->RenderFloat("float_value", 0.0) + ->RenderInt64("int64_value", 0) + ->RenderUint64("uint64_value", 0) + ->RenderInt32("int32_value", 0) + ->RenderUint32("uint32_value", 0) + ->RenderBool("bool_value", false) + ->RenderString("string_value", "") + ->RenderString("unknown", "abc") + ->StartObject("unknown_object") + ->RenderString("unknown", "def") + ->EndObject() + ->EndObject(); + + // Actual testing + testing_->StartObject("") + ->RenderDouble("double_value", 1.0) + ->RenderString("unknown", "abc") + ->StartObject("unknown_object") + ->RenderString("unknown", "def") + ->EndObject() + ->EndObject(); +} + +} // namespace testing +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/objectivec/Tests/Filter2.txt b/src/google/protobuf/util/internal/error_listener.cc index 5a2bb0f8..538307ba 100644 --- a/objectivec/Tests/Filter2.txt +++ b/src/google/protobuf/util/internal/error_listener.cc @@ -1,5 +1,5 @@ // Protocol Buffers - Google's data interchange format -// Copyright 2014 Google Inc. All rights reserved. +// Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without @@ -28,8 +28,15 @@ // (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/util/internal/error_listener.h> -// Test the filter system for the ObjC Protocol Buffer Compiler to test -// multiple filter support. +namespace google { +namespace protobuf { +namespace util { +namespace converter { -Other + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/error_listener.h b/src/google/protobuf/util/internal/error_listener.h new file mode 100644 index 00000000..9b907df5 --- /dev/null +++ b/src/google/protobuf/util/internal/error_listener.h @@ -0,0 +1,99 @@ +// 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_UTIL_CONVERTER_ERROR_LISTENER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_ERROR_LISTENER_H__ + +#include <memory> +#ifndef _SHARED_PTR_H +#include <google/protobuf/stubs/shared_ptr.h> +#endif +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/util/internal/location_tracker.h> +#include <google/protobuf/stubs/stringpiece.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// Interface for error listener. +class LIBPROTOBUF_EXPORT ErrorListener { + public: + virtual ~ErrorListener() {} + + // Reports an invalid name at the given location. + virtual void InvalidName(const LocationTrackerInterface& loc, + StringPiece unknown_name, StringPiece message) = 0; + + // Reports an invalid value for a field. + virtual void InvalidValue(const LocationTrackerInterface& loc, + StringPiece type_name, StringPiece value) = 0; + + // Reports a missing required field. + virtual void MissingField(const LocationTrackerInterface& loc, + StringPiece missing_name) = 0; + + protected: + ErrorListener() {} + + private: + // Do not add any data members to this class. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorListener); +}; + +// An error listener that ignores all errors. +class LIBPROTOBUF_EXPORT NoopErrorListener : public ErrorListener { + public: + NoopErrorListener() {} + virtual ~NoopErrorListener() {} + + virtual void InvalidName(const LocationTrackerInterface& loc, + StringPiece unknown_name, StringPiece message) {} + + virtual void InvalidValue(const LocationTrackerInterface& loc, + StringPiece type_name, StringPiece value) {} + + virtual void MissingField(const LocationTrackerInterface& loc, + StringPiece missing_name) {} + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(NoopErrorListener); +}; + + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_ERROR_LISTENER_H__ diff --git a/src/google/protobuf/util/internal/expecting_objectwriter.h b/src/google/protobuf/util/internal/expecting_objectwriter.h new file mode 100644 index 00000000..ae98ddd8 --- /dev/null +++ b/src/google/protobuf/util/internal/expecting_objectwriter.h @@ -0,0 +1,238 @@ +// 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_UTIL_CONVERTER_EXPECTING_OBJECTWRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_EXPECTING_OBJECTWRITER_H__ + +// An implementation of ObjectWriter that automatically sets the +// gmock expectations for the response to a method. Every method +// returns the object itself for chaining. +// +// Usage: +// // Setup +// MockObjectWriter mock; +// ExpectingObjectWriter ow(&mock); +// +// // Set expectation +// ow.StartObject("") +// ->RenderString("key", "value") +// ->EndObject(); +// +// // Actual testing +// mock.StartObject(StringPiece()) +// ->RenderString("key", "value") +// ->EndObject(); + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/util/internal/object_writer.h> +#include <gmock/gmock.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +using testing::IsEmpty; +using testing::NanSensitiveDoubleEq; +using testing::NanSensitiveFloatEq; +using testing::Return; +using testing::StrEq; +using testing::TypedEq; + +class MockObjectWriter : public ObjectWriter { + public: + MockObjectWriter() {} + + MOCK_METHOD1(StartObject, ObjectWriter*(StringPiece)); + MOCK_METHOD0(EndObject, ObjectWriter*()); + MOCK_METHOD1(StartList, ObjectWriter*(StringPiece)); + MOCK_METHOD0(EndList, ObjectWriter*()); + MOCK_METHOD2(RenderBool, ObjectWriter*(StringPiece, bool)); + MOCK_METHOD2(RenderInt32, ObjectWriter*(StringPiece, int32)); + MOCK_METHOD2(RenderUint32, ObjectWriter*(StringPiece, uint32)); + MOCK_METHOD2(RenderInt64, ObjectWriter*(StringPiece, int64)); + MOCK_METHOD2(RenderUint64, ObjectWriter*(StringPiece, uint64)); + MOCK_METHOD2(RenderDouble, ObjectWriter*(StringPiece, double)); + MOCK_METHOD2(RenderFloat, ObjectWriter*(StringPiece, float)); + MOCK_METHOD2(RenderString, ObjectWriter*(StringPiece, StringPiece)); + MOCK_METHOD2(RenderBytes, ObjectWriter*(StringPiece, StringPiece)); + MOCK_METHOD1(RenderNull, ObjectWriter*(StringPiece)); +}; + +class ExpectingObjectWriter : public ObjectWriter { + public: + explicit ExpectingObjectWriter(MockObjectWriter* mock) : mock_(mock) {} + + virtual ObjectWriter* StartObject(StringPiece name) { + (name.empty() + ? EXPECT_CALL(*mock_, StartObject(IsEmpty())) + : EXPECT_CALL(*mock_, StartObject(StrEq(name.ToString())))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* EndObject() { + EXPECT_CALL(*mock_, EndObject()) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* StartList(StringPiece name) { + (name.empty() + ? EXPECT_CALL(*mock_, StartList(IsEmpty())) + : EXPECT_CALL(*mock_, StartList(StrEq(name.ToString())))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* EndList() { + EXPECT_CALL(*mock_, EndList()) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* RenderBool(StringPiece name, bool value) { + (name.empty() + ? EXPECT_CALL(*mock_, RenderBool(IsEmpty(), TypedEq<bool>(value))) + : EXPECT_CALL(*mock_, RenderBool(StrEq(name.ToString()), + TypedEq<bool>(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* RenderInt32(StringPiece name, int32 value) { + (name.empty() + ? EXPECT_CALL(*mock_, RenderInt32(IsEmpty(), TypedEq<int32>(value))) + : EXPECT_CALL(*mock_, RenderInt32(StrEq(name.ToString()), + TypedEq<int32>(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* RenderUint32(StringPiece name, uint32 value) { + (name.empty() + ? EXPECT_CALL(*mock_, RenderUint32(IsEmpty(), TypedEq<uint32>(value))) + : EXPECT_CALL(*mock_, RenderUint32(StrEq(name.ToString()), + TypedEq<uint32>(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* RenderInt64(StringPiece name, int64 value) { + (name.empty() + ? EXPECT_CALL(*mock_, RenderInt64(IsEmpty(), TypedEq<int64>(value))) + : EXPECT_CALL(*mock_, RenderInt64(StrEq(name.ToString()), + TypedEq<int64>(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* RenderUint64(StringPiece name, uint64 value) { + (name.empty() + ? EXPECT_CALL(*mock_, RenderUint64(IsEmpty(), TypedEq<uint64>(value))) + : EXPECT_CALL(*mock_, RenderUint64(StrEq(name.ToString()), + TypedEq<uint64>(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* RenderDouble(StringPiece name, double value) { + (name.empty() + ? EXPECT_CALL(*mock_, RenderDouble(IsEmpty(), + NanSensitiveDoubleEq(value))) + : EXPECT_CALL(*mock_, RenderDouble(StrEq(name.ToString()), + NanSensitiveDoubleEq(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* RenderFloat(StringPiece name, float value) { + (name.empty() + ? EXPECT_CALL(*mock_, RenderFloat(IsEmpty(), + NanSensitiveFloatEq(value))) + : EXPECT_CALL(*mock_, RenderFloat(StrEq(name.ToString()), + NanSensitiveFloatEq(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* RenderString(StringPiece name, StringPiece value) { + (name.empty() + ? EXPECT_CALL(*mock_, RenderString(IsEmpty(), + TypedEq<StringPiece>(value.ToString()))) + : EXPECT_CALL(*mock_, RenderString(StrEq(name.ToString()), + TypedEq<StringPiece>(value.ToString())))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + virtual ObjectWriter* RenderBytes(StringPiece name, StringPiece value) { + (name.empty() + ? EXPECT_CALL(*mock_, RenderBytes(IsEmpty(), TypedEq<StringPiece>( + value.ToString()))) + : EXPECT_CALL(*mock_, + RenderBytes(StrEq(name.ToString()), + TypedEq<StringPiece>(value.ToString())))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* RenderNull(StringPiece name) { + (name.empty() ? EXPECT_CALL(*mock_, RenderNull(IsEmpty())) + : EXPECT_CALL(*mock_, RenderNull(StrEq(name.ToString()))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation()); + return this; + } + + private: + MockObjectWriter* mock_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ExpectingObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_EXPECTING_OBJECTWRITER_H__ diff --git a/src/google/protobuf/util/internal/field_mask_utility.cc b/src/google/protobuf/util/internal/field_mask_utility.cc new file mode 100644 index 00000000..92468959 --- /dev/null +++ b/src/google/protobuf/util/internal/field_mask_utility.cc @@ -0,0 +1,228 @@ +// 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/util/internal/field_mask_utility.h> + +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/status_macros.h> + +namespace google { + +namespace protobuf { +namespace util { +namespace converter { + +namespace { +inline util::Status CallPathSink(PathSinkCallback path_sink, + StringPiece arg) { + return path_sink->Run(arg); +} + +util::Status CreatePublicError(util::error::Code code, + const string& message) { + return util::Status(code, message); +} + +// Appends a FieldMask path segment to a prefix. +string AppendPathSegmentToPrefix(StringPiece prefix, StringPiece segment) { + if (prefix.empty()) { + return segment.ToString(); + } + if (segment.empty()) { + return prefix.ToString(); + } + // If the segment is a map key, appends it to the prefix without the ".". + if (segment.starts_with("[\"")) { + return StrCat(prefix, segment); + } + return StrCat(prefix, ".", segment); +} + +} // namespace + +string ConvertFieldMaskPath(const StringPiece path, + ConverterCallback converter) { + string result; + result.reserve(path.size() << 1); + + bool is_quoted = false; + bool is_escaping = false; + int current_segment_start = 0; + + // Loops until 1 passed the end of the input to make handling the last + // segment easier. + for (size_t i = 0; i <= path.size(); ++i) { + // Outputs quoted string as-is. + if (is_quoted) { + if (i == path.size()) { + break; + } + result.push_back(path[i]); + if (is_escaping) { + is_escaping = false; + } else if (path[i] == '\\') { + is_escaping = true; + } else if (path[i] == '\"') { + current_segment_start = i + 1; + is_quoted = false; + } + continue; + } + if (i == path.size() || path[i] == '.' || path[i] == '(' || + path[i] == ')' || path[i] == '\"') { + result += converter( + path.substr(current_segment_start, i - current_segment_start)); + if (i < path.size()) { + result.push_back(path[i]); + } + current_segment_start = i + 1; + } + if (i < path.size() && path[i] == '\"') { + is_quoted = true; + } + } + return result; +} + +util::Status DecodeCompactFieldMaskPaths(StringPiece paths, + PathSinkCallback path_sink) { + stack<string> prefix; + int length = paths.length(); + int previous_position = 0; + bool in_map_key = false; + bool is_escaping = false; + // Loops until 1 passed the end of the input to make the handle of the last + // segment easier. + for (int i = 0; i <= length; ++i) { + if (i != length) { + // Skips everything in a map key until we hit the end of it, which is + // marked by an un-escaped '"' immediately followed by a ']'. + if (in_map_key) { + if (is_escaping) { + is_escaping = false; + continue; + } + if (paths[i] == '\\') { + is_escaping = true; + continue; + } + if (paths[i] != '\"') { + continue; + } + // Un-escaped '"' must be followed with a ']'. + if (i >= length - 1 || paths[i + 1] != ']') { + return CreatePublicError( + util::error::INVALID_ARGUMENT, + StrCat("Invalid FieldMask '", paths, + "'. Map keys should be represented as [\"some_key\"].")); + } + // The end of the map key ("\"]") has been found. + in_map_key = false; + // Skips ']'. + i++; + // Checks whether the key ends at the end of a path segment. + if (i < length - 1 && paths[i + 1] != '.' && paths[i + 1] != ',' && + paths[i + 1] != ')' && paths[i + 1] != '(') { + return CreatePublicError( + util::error::INVALID_ARGUMENT, + StrCat("Invalid FieldMask '", paths, + "'. Map keys should be at the end of a path segment.")); + } + is_escaping = false; + continue; + } + + // We are not in a map key, look for the start of one. + if (paths[i] == '[') { + if (i >= length - 1 || paths[i + 1] != '\"') { + return CreatePublicError( + util::error::INVALID_ARGUMENT, + StrCat("Invalid FieldMask '", paths, + "'. Map keys should be represented as [\"some_key\"].")); + } + // "[\"" starts a map key. + in_map_key = true; + i++; // Skips the '\"'. + continue; + } + // If the current character is not a special character (',', '(' or ')'), + // continue to the next. + if (paths[i] != ',' && paths[i] != ')' && paths[i] != '(') { + continue; + } + } + // Gets the current segment - sub-string between previous position (after + // '(', ')', ',', or the beginning of the input) and the current position. + StringPiece segment = + paths.substr(previous_position, i - previous_position); + string current_prefix = prefix.empty() ? "" : prefix.top(); + + if (i < length && paths[i] == '(') { + // Builds a prefix and save it into the stack. + prefix.push(AppendPathSegmentToPrefix(current_prefix, segment)); + } else if (!segment.empty()) { + // When the current charactor is ')', ',' or the current position has + // passed the end of the input, builds and outputs a new paths by + // concatenating the last prefix with the current segment. + RETURN_IF_ERROR(CallPathSink( + path_sink, AppendPathSegmentToPrefix(current_prefix, segment))); + } + + // Removes the last prefix after seeing a ')'. + if (i < length && paths[i] == ')') { + if (prefix.empty()) { + return CreatePublicError( + util::error::INVALID_ARGUMENT, + StrCat("Invalid FieldMask '", paths, + "'. Cannot find matching '(' for all ')'.")); + } + prefix.pop(); + } + previous_position = i + 1; + } + if (in_map_key) { + return CreatePublicError( + util::error::INVALID_ARGUMENT, + StrCat("Invalid FieldMask '", paths, + "'. Cannot find matching ']' for all '['.")); + } + if (!prefix.empty()) { + return CreatePublicError( + util::error::INVALID_ARGUMENT, + StrCat("Invalid FieldMask '", paths, + "'. Cannot find matching ')' for all '('.")); + } + return util::Status::OK; +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/field_mask_utility.h b/src/google/protobuf/util/internal/field_mask_utility.h new file mode 100644 index 00000000..59f36f75 --- /dev/null +++ b/src/google/protobuf/util/internal/field_mask_utility.h @@ -0,0 +1,72 @@ +// 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. + +// FieldMask related utility methods. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_FIELD_MASK_UTILITY_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_FIELD_MASK_UTILITY_H__ + +#include <functional> +#include <stack> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/stringpiece.h> +#include <google/protobuf/stubs/status.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +typedef string (*ConverterCallback)(StringPiece); +typedef ResultCallback1<util::Status, StringPiece>* PathSinkCallback; + +// Applies a 'converter' to each segment of a FieldMask path and returns the +// result. Quoted strings in the 'path' are copied to the output as-is without +// converting their content. Escaping is supported within quoted strings. +// For example, "ab\"_c" will be returned as "ab\"_c" without any changes. +string ConvertFieldMaskPath(const StringPiece path, + ConverterCallback converter); + +// Decodes a compact list of FieldMasks. For example, "a.b,a.c.d,a.c.e" will be +// decoded into a list of field paths - "a.b", "a.c.d", "a.c.e". And the results +// will be sent to 'path_sink', i.e. 'path_sink' will be called once per +// resulting path. +// Note that we also support Apiary style FieldMask form. The above example in +// the Apiary style will look like "a.b,a.c(d,e)". +util::Status DecodeCompactFieldMaskPaths(StringPiece paths, + PathSinkCallback path_sink); + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_FIELD_MASK_UTILITY_H__ diff --git a/src/google/protobuf/util/internal/json_escaping.cc b/src/google/protobuf/util/internal/json_escaping.cc new file mode 100644 index 00000000..5ac23421 --- /dev/null +++ b/src/google/protobuf/util/internal/json_escaping.cc @@ -0,0 +1,403 @@ +// 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/util/internal/json_escaping.h> + +#include <google/protobuf/stubs/common.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +namespace { + +// Array of hex characters for conversion to hex. +static const char kHex[] = "0123456789abcdef"; + +// Characters 0x00 to 0x9f are very commonly used, so we provide a special +// table lookup. +// +// For unicode code point ch < 0xa0: +// kCommonEscapes[ch] is the escaped string of ch, if escaping is needed; +// or an empty string, if escaping is not needed. +static const char kCommonEscapes[160][7] = { + // C0 (ASCII and derivatives) control characters + "\\u0000", "\\u0001", "\\u0002", "\\u0003", // 0x00 + "\\u0004", "\\u0005", "\\u0006", "\\u0007", + "\\b", "\\t", "\\n", "\\u000b", + "\\f", "\\r", "\\u000e", "\\u000f", + "\\u0010", "\\u0011", "\\u0012", "\\u0013", // 0x10 + "\\u0014", "\\u0015", "\\u0016", "\\u0017", + "\\u0018", "\\u0019", "\\u001a", "\\u001b", + "\\u001c", "\\u001d", "\\u001e", "\\u001f", + // Escaping of " and \ are required by www.json.org string definition. + // Escaping of < and > are required for HTML security. + "", "", "\\\"", "", "", "", "", "", // 0x20 + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", // 0x30 + "", "", "", "", "\\u003c", "", "\\u003e", "", + "", "", "", "", "", "", "", "", // 0x40 + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", // 0x50 + "", "", "", "", "\\\\", "", "", "", + "", "", "", "", "", "", "", "", // 0x60 + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", // 0x70 + "", "", "", "", "", "", "", "\\u007f", + // C1 (ISO 8859 and Unicode) extended control characters + "\\u0080", "\\u0081", "\\u0082", "\\u0083", // 0x80 + "\\u0084", "\\u0085", "\\u0086", "\\u0087", + "\\u0088", "\\u0089", "\\u008a", "\\u008b", + "\\u008c", "\\u008d", "\\u008e", "\\u008f", + "\\u0090", "\\u0091", "\\u0092", "\\u0093", // 0x90 + "\\u0094", "\\u0095", "\\u0096", "\\u0097", + "\\u0098", "\\u0099", "\\u009a", "\\u009b", + "\\u009c", "\\u009d", "\\u009e", "\\u009f" +}; + +// Determines if the given char value is a unicode high-surrogate code unit. +// Such values do not represent characters by themselves, but are used in the +// representation of supplementary characters in the utf-16 encoding. +inline bool IsHighSurrogate(uint16 c) { + // Optimized form of: + // return c >= kMinHighSurrogate && c <= kMaxHighSurrogate; + // (Reduced from 3 ALU instructions to 2 ALU instructions) + return (c & ~(JsonEscaping::kMaxHighSurrogate - + JsonEscaping::kMinHighSurrogate)) + == JsonEscaping::kMinHighSurrogate; +} + +// Determines if the given char value is a unicode low-surrogate code unit. +// Such values do not represent characters by themselves, but are used in the +// representation of supplementary characters in the utf-16 encoding. +inline bool IsLowSurrogate(uint16 c) { + // Optimized form of: + // return c >= kMinLowSurrogate && c <= kMaxLowSurrogate; + // (Reduced from 3 ALU instructions to 2 ALU instructions) + return (c & ~(JsonEscaping::kMaxLowSurrogate - + JsonEscaping::kMinLowSurrogate)) + == JsonEscaping::kMinLowSurrogate; +} + +// Determines if the given char value is a unicode surrogate code unit (either +// high-surrogate or low-surrogate). +inline bool IsSurrogate(uint32 c) { + // Optimized form of: + // return c >= kMinHighSurrogate && c <= kMaxLowSurrogate; + // (Reduced from 3 ALU instructions to 2 ALU instructions) + return (c & 0xfffff800) == JsonEscaping::kMinHighSurrogate; +} + +// Returns true if the given unicode code point cp is +// in the supplementary character range. +inline bool IsSupplementalCodePoint(uint32 cp) { + // Optimized form of: + // return kMinSupplementaryCodePoint <= cp && cp <= kMaxCodePoint; + // (Reduced from 3 ALU instructions to 2 ALU instructions) + return (cp & ~(JsonEscaping::kMinSupplementaryCodePoint - 1)) + < JsonEscaping::kMaxCodePoint; +} + +// Returns true if the given unicode code point cp is a valid +// unicode code point (i.e. in the range 0 <= cp <= kMaxCodePoint). +inline bool IsValidCodePoint(uint32 cp) { + return cp <= JsonEscaping::kMaxCodePoint; +} + +// Converts the specified surrogate pair to its supplementary code point value. +// It is the callers' responsibility to validate the specified surrogate pair. +inline uint32 ToCodePoint(uint16 high, uint16 low) { + // Optimized form of: + // return ((high - kMinHighSurrogate) << 10) + // + (low - kMinLowSurrogate) + // + kMinSupplementaryCodePoint; + // (Reduced from 5 ALU instructions to 3 ALU instructions) + return (high << 10) + low + + (JsonEscaping::kMinSupplementaryCodePoint + - (static_cast<unsigned>(JsonEscaping::kMinHighSurrogate) << 10) + - JsonEscaping::kMinLowSurrogate); +} + +// Returns the low surrogate for the given unicode code point. The result is +// meaningless if the given code point is not a supplementary character. +inline uint16 ToLowSurrogate(uint32 cp) { + return (cp & (JsonEscaping::kMaxLowSurrogate + - JsonEscaping::kMinLowSurrogate)) + + JsonEscaping::kMinLowSurrogate; +} + +// Returns the high surrogate for the given unicode code point. The result is +// meaningless if the given code point is not a supplementary character. +inline uint16 ToHighSurrogate(uint32 cp) { + return (cp >> 10) + (JsonEscaping::kMinHighSurrogate - + (JsonEscaping::kMinSupplementaryCodePoint >> 10)); +} + +// Input str is encoded in UTF-8. A unicode code point could be encoded in +// UTF-8 using anywhere from 1 to 4 characters, and it could span multiple +// reads of the ByteSource. +// +// This function reads the next unicode code point from the input (str) at +// the given position (index), taking into account any left-over partial +// code point from the previous iteration (cp), together with the number +// of characters left to read to complete this code point (num_left). +// +// This function assumes that the input (str) is valid at the given position +// (index). In order words, at least one character could be read successfully. +// +// The code point read (partial or complete) is stored in (cp). Upon return, +// (num_left) stores the number of characters that has yet to be read in +// order to complete the current unicode code point. If the read is complete, +// then (num_left) is 0. Also, (num_read) is the number of characters read. +// +// Returns false if we encounter an invalid UTF-8 string. Returns true +// otherwise, including the case when we reach the end of the input (str) +// before a complete unicode code point is read. +bool ReadCodePoint(StringPiece str, int index, + uint32 *cp, int* num_left, int *num_read) { + if (*num_left == 0) { + // Last read was complete. Start reading a new unicode code point. + *cp = str[index++]; + *num_read = 1; + // The length of the code point is determined from reading the first byte. + // + // If the first byte is between: + // 0..0x7f: that's the value of the code point. + // 0x80..0xbf: <invalid> + // 0xc0..0xdf: 11-bit code point encoded in 2 bytes. + // bit 10-6, bit 5-0 + // 0xe0..0xef: 16-bit code point encoded in 3 bytes. + // bit 15-12, bit 11-6, bit 5-0 + // 0xf0..0xf7: 21-bit code point encoded in 4 bytes. + // bit 20-18, bit 17-12, bit 11-6, bit 5-0 + // 0xf8..0xff: <invalid> + // + // Meaning of each bit: + // <msb> bit 7: 0 - single byte code point: bits 6-0 are values. + // 1 - multibyte code point + // bit 6: 0 - subsequent bytes of multibyte code point: + // bits 5-0 are values. + // 1 - first byte of multibyte code point + // bit 5: 0 - first byte of 2-byte code point: bits 4-0 are values. + // 1 - first byte of code point with >= 3 bytes. + // bit 4: 0 - first byte of 3-byte code point: bits 3-0 are values. + // 1 - first byte of code point with >= 4 bytes. + // bit 3: 0 - first byte of 4-byte code point: bits 2-0 are values. + // 1 - reserved for future expansion. + if (*cp <= 0x7f) { + return true; + } else if (*cp <= 0xbf) { + return false; + } else if (*cp <= 0xdf) { + *cp &= 0x1f; + *num_left = 1; + } else if (*cp <= 0xef) { + *cp &= 0x0f; + *num_left = 2; + } else if (*cp <= 0xf7) { + *cp &= 0x07; + *num_left = 3; + } else { + return false; + } + } else { + // Last read was partial. Initialize num_read to 0 and continue reading + // the last unicode code point. + *num_read = 0; + } + while (*num_left > 0 && index < str.size()) { + uint32 ch = str[index++]; + --(*num_left); + ++(*num_read); + *cp = (*cp << 6) | (ch & 0x3f); + if (ch < 0x80 || ch > 0xbf) return false; + } + return *num_left > 0 || (!IsSurrogate(*cp) && IsValidCodePoint(*cp)); +} + +// Stores the 16-bit unicode code point as its hexadecimal digits in buffer +// and returns a StringPiece that points to this buffer. The input buffer needs +// to be at least 6 bytes long. +StringPiece ToHex(uint16 cp, char* buffer) { + buffer[5] = kHex[cp & 0x0f]; + cp >>= 4; + buffer[4] = kHex[cp & 0x0f]; + cp >>= 4; + buffer[3] = kHex[cp & 0x0f]; + cp >>= 4; + buffer[2] = kHex[cp & 0x0f]; + return StringPiece(buffer, 0, 6); +} + +// Stores the 32-bit unicode code point as its hexadecimal digits in buffer +// and returns a StringPiece that points to this buffer. The input buffer needs +// to be at least 12 bytes long. +StringPiece ToSurrogateHex(uint32 cp, char* buffer) { + uint16 low = ToLowSurrogate(cp); + uint16 high = ToHighSurrogate(cp); + + buffer[11] = kHex[low & 0x0f]; + low >>= 4; + buffer[10] = kHex[low & 0x0f]; + low >>= 4; + buffer[9] = kHex[low & 0x0f]; + low >>= 4; + buffer[8] = kHex[low & 0x0f]; + + buffer[5] = kHex[high & 0x0f]; + high >>= 4; + buffer[4] = kHex[high & 0x0f]; + high >>= 4; + buffer[3] = kHex[high & 0x0f]; + high >>= 4; + buffer[2] = kHex[high & 0x0f]; + + return StringPiece(buffer, 12); +} + +// If the given unicode code point needs escaping, then returns the +// escaped form. The returned StringPiece either points to statically +// pre-allocated char[] or to the given buffer. The input buffer needs +// to be at least 12 bytes long. +// +// If the given unicode code point does not need escaping, an empty +// StringPiece is returned. +StringPiece EscapeCodePoint(uint32 cp, char* buffer) { + if (cp < 0xa0) return kCommonEscapes[cp]; + switch (cp) { + // These are not required by json spec + // but used to prevent security bugs in javascript. + case 0xfeff: // Zero width no-break space + case 0xfff9: // Interlinear annotation anchor + case 0xfffa: // Interlinear annotation separator + case 0xfffb: // Interlinear annotation terminator + + case 0x00ad: // Soft-hyphen + case 0x06dd: // Arabic end of ayah + case 0x070f: // Syriac abbreviation mark + case 0x17b4: // Khmer vowel inherent Aq + case 0x17b5: // Khmer vowel inherent Aa + return ToHex(cp, buffer); + + default: + if ((cp >= 0x0600 && cp <= 0x0603) || // Arabic signs + (cp >= 0x200b && cp <= 0x200f) || // Zero width etc. + (cp >= 0x2028 && cp <= 0x202e) || // Separators etc. + (cp >= 0x2060 && cp <= 0x2064) || // Invisible etc. + (cp >= 0x206a && cp <= 0x206f)) { // Shaping etc. + return ToHex(cp, buffer); + } + + if (cp == 0x000e0001 || // Language tag + (cp >= 0x0001d173 && cp <= 0x0001d17a) || // Music formatting + (cp >= 0x000e0020 && cp <= 0x000e007f)) { // TAG symbols + return ToSurrogateHex(cp, buffer); + } + } + return StringPiece(); +} + +// Tries to escape the given code point first. If the given code point +// does not need to be escaped, but force_output is true, then render +// the given multi-byte code point in UTF8 in the buffer and returns it. +StringPiece EscapeCodePoint(uint32 cp, char* buffer, bool force_output) { + StringPiece sp = EscapeCodePoint(cp, buffer); + if (force_output && sp.empty()) { + buffer[5] = (cp & 0x3f) | 0x80; + cp >>= 6; + if (cp <= 0x1f) { + buffer[4] = cp | 0xc0; + sp.set(buffer + 4, 2); + return sp; + } + buffer[4] = (cp & 0x3f) | 0x80; + cp >>= 6; + if (cp <= 0x0f) { + buffer[3] = cp | 0xe0; + sp.set(buffer + 3, 3); + return sp; + } + buffer[3] = (cp & 0x3f) | 0x80; + buffer[2] = ((cp >> 6) & 0x07) | 0xf0; + sp.set(buffer + 2, 4); + } + return sp; +} + +} // namespace + +void JsonEscaping::Escape(strings::ByteSource* input, + strings::ByteSink* output) { + char buffer[12] = "\\udead\\ubee"; + uint32 cp = 0; // Current unicode code point. + int num_left = 0; // Num of chars to read to complete the code point. + while (input->Available() > 0) { + StringPiece str = input->Peek(); + StringPiece escaped; + int i = 0; + int num_read; + bool ok; + bool cp_was_split = num_left > 0; + // Loop until we encounter either + // i) a code point that needs to be escaped; or + // ii) a split code point is completely read; or + // iii) a character that is not a valid utf8; or + // iv) end of the StringPiece str is reached. + do { + ok = ReadCodePoint(str, i, &cp, &num_left, &num_read); + if (num_left > 0 || !ok) break; // case iii or iv + escaped = EscapeCodePoint(cp, buffer, cp_was_split); + if (!escaped.empty()) break; // case i or ii + i += num_read; + num_read = 0; + } while (i < str.length()); // case iv + // First copy the un-escaped prefix, if any, to the output ByteSink. + if (i > 0) input->CopyTo(output, i); + if (num_read > 0) input->Skip(num_read); + if (!ok) { + // Case iii: Report error. + // TODO(wpoon): Add error reporting. + num_left = 0; + } else if (num_left == 0 && !escaped.empty()) { + // Case i or ii: Append the escaped code point to the output ByteSink. + output->Append(escaped.data(), escaped.size()); + } + } + if (num_left > 0) { + // Treat as case iii: report error. + // TODO(wpoon): Add error reporting. + } +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/json_escaping.h b/src/google/protobuf/util/internal/json_escaping.h new file mode 100644 index 00000000..e3e329fc --- /dev/null +++ b/src/google/protobuf/util/internal/json_escaping.h @@ -0,0 +1,91 @@ +// 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 NET_PROTO2_UTIL_CONVERTER_STRINGS_JSON_ESCAPING_H_ +#define NET_PROTO2_UTIL_CONVERTER_STRINGS_JSON_ESCAPING_H_ + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/bytestream.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +class JsonEscaping { + public: + // The minimum value of a unicode high-surrogate code unit in the utf-16 + // encoding. A high-surrogate is also known as a leading-surrogate. + // See http://www.unicode.org/glossary/#high_surrogate_code_unit + static const uint16 kMinHighSurrogate = 0xd800; + + // The maximum value of a unicide high-surrogate code unit in the utf-16 + // encoding. A high-surrogate is also known as a leading-surrogate. + // See http://www.unicode.org/glossary/#high_surrogate_code_unit + static const uint16 kMaxHighSurrogate = 0xdbff; + + // The minimum value of a unicode low-surrogate code unit in the utf-16 + // encoding. A low-surrogate is also known as a trailing-surrogate. + // See http://www.unicode.org/glossary/#low_surrogate_code_unit + static const uint16 kMinLowSurrogate = 0xdc00; + + // The maximum value of a unicode low-surrogate code unit in the utf-16 + // encoding. A low-surrogate is also known as a trailing surrogate. + // See http://www.unicode.org/glossary/#low_surrogate_code_unit + static const uint16 kMaxLowSurrogate = 0xdfff; + + // The minimum value of a unicode supplementary code point. + // See http://www.unicode.org/glossary/#supplementary_code_point + static const uint32 kMinSupplementaryCodePoint = 0x010000; + + // The minimum value of a unicode code point. + // See http://www.unicode.org/glossary/#code_point + static const uint32 kMinCodePoint = 0x000000; + + // The maximum value of a unicode code point. + // See http://www.unicode.org/glossary/#code_point + static const uint32 kMaxCodePoint = 0x10ffff; + + JsonEscaping() {} + virtual ~JsonEscaping() {} + + // Escape the given ByteSource to the given ByteSink. + static void Escape(strings::ByteSource* input, strings::ByteSink* output); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JsonEscaping); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +#endif // NET_PROTO2_UTIL_CONVERTER_STRINGS_JSON_ESCAPING_H_ +} // namespace google diff --git a/src/google/protobuf/util/internal/json_objectwriter.cc b/src/google/protobuf/util/internal/json_objectwriter.cc new file mode 100644 index 00000000..0c41515f --- /dev/null +++ b/src/google/protobuf/util/internal/json_objectwriter.cc @@ -0,0 +1,175 @@ +// 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/util/internal/json_objectwriter.h> + +#include <math.h> + +#include <google/protobuf/stubs/casts.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/util/internal/utility.h> +#include <google/protobuf/util/internal/json_escaping.h> +#include <google/protobuf/stubs/strutil.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +using strings::ArrayByteSource; + +JsonObjectWriter::~JsonObjectWriter() { + if (!element_->is_root()) { + GOOGLE_LOG(WARNING) << "JsonObjectWriter was not fully closed."; + } +} + +JsonObjectWriter* JsonObjectWriter::StartObject(StringPiece name) { + WritePrefix(name); + WriteChar('{'); + Push(); + return this; +} + +JsonObjectWriter* JsonObjectWriter::EndObject() { + Pop(); + WriteChar('}'); + if (element()->is_root()) NewLine(); + return this; +} + +JsonObjectWriter* JsonObjectWriter::StartList(StringPiece name) { + WritePrefix(name); + WriteChar('['); + Push(); + return this; +} + +JsonObjectWriter* JsonObjectWriter::EndList() { + Pop(); + WriteChar(']'); + if (element()->is_root()) NewLine(); + return this; +} + +JsonObjectWriter* JsonObjectWriter::RenderBool(StringPiece name, + bool value) { + return RenderSimple(name, value ? "true" : "false"); +} + +JsonObjectWriter* JsonObjectWriter::RenderInt32(StringPiece name, + int32 value) { + return RenderSimple(name, SimpleItoa(value)); +} + +JsonObjectWriter* JsonObjectWriter::RenderUint32(StringPiece name, + uint32 value) { + return RenderSimple(name, SimpleItoa(value)); +} + +JsonObjectWriter* JsonObjectWriter::RenderInt64(StringPiece name, + int64 value) { + WritePrefix(name); + WriteChar('"'); + stream_->WriteString(SimpleItoa(value)); + WriteChar('"'); + return this; +} + +JsonObjectWriter* JsonObjectWriter::RenderUint64(StringPiece name, + uint64 value) { + WritePrefix(name); + WriteChar('"'); + stream_->WriteString(SimpleItoa(value)); + WriteChar('"'); + return this; +} + +JsonObjectWriter* JsonObjectWriter::RenderDouble(StringPiece name, + double value) { + if (isfinite(value)) return RenderSimple(name, SimpleDtoa(value)); + + // Render quoted with NaN/Infinity-aware DoubleAsString. + return RenderString(name, DoubleAsString(value)); +} + +JsonObjectWriter* JsonObjectWriter::RenderFloat(StringPiece name, + float value) { + if (isfinite(value)) return RenderSimple(name, SimpleFtoa(value)); + + // Render quoted with NaN/Infinity-aware FloatAsString. + return RenderString(name, FloatAsString(value)); +} + +JsonObjectWriter* JsonObjectWriter::RenderString(StringPiece name, + StringPiece value) { + WritePrefix(name); + WriteChar('"'); + ArrayByteSource source(value); + JsonEscaping::Escape(&source, &sink_); + WriteChar('"'); + return this; +} + +JsonObjectWriter* JsonObjectWriter::RenderBytes(StringPiece name, + StringPiece value) { + WritePrefix(name); + string base64; + WebSafeBase64EscapeWithPadding(value, &base64); + WriteChar('"'); + // TODO(wpoon): Consider a ByteSink solution that writes the base64 bytes + // directly to the stream, rather than first putting them + // into a string and then writing them to the stream. + stream_->WriteRaw(base64.data(), base64.size()); + WriteChar('"'); + return this; +} + +JsonObjectWriter* JsonObjectWriter::RenderNull(StringPiece name) { + return RenderSimple(name, "null"); +} + +void JsonObjectWriter::WritePrefix(StringPiece name) { + bool not_first = !element()->is_first(); + if (not_first) WriteChar(','); + if (not_first || !element()->is_root()) NewLine(); + if (!name.empty()) { + WriteChar('"'); + ArrayByteSource source(name); + JsonEscaping::Escape(&source, &sink_); + stream_->WriteString("\":"); + if (!indent_string_.empty()) WriteChar(' '); + } +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/json_objectwriter.h b/src/google/protobuf/util/internal/json_objectwriter.h new file mode 100644 index 00000000..761a0a10 --- /dev/null +++ b/src/google/protobuf/util/internal/json_objectwriter.h @@ -0,0 +1,206 @@ +// 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_UTIL_CONVERTER_JSON_OBJECTWRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_OBJECTWRITER_H__ + +#include <memory> +#ifndef _SHARED_PTR_H +#include <google/protobuf/stubs/shared_ptr.h> +#endif +#include <string> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/util/internal/structured_objectwriter.h> +#include <google/protobuf/stubs/bytestream.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// An ObjectWriter implementation that outputs JSON. This ObjectWriter +// supports writing a compact form or a pretty printed form. +// +// Sample usage: +// string output; +// StringOutputStream* str_stream = new StringOutputStream(&output); +// CodedOutputStream* out_stream = new CodedOutputStream(str_stream); +// JsonObjectWriter* ow = new JsonObjectWriter(" ", out_stream); +// ow->StartObject("") +// ->RenderString("name", "value") +// ->RenderString("emptystring", string()) +// ->StartObject("nested") +// ->RenderInt64("light", 299792458); +// ->RenderDouble("pi", 3.141592653589793); +// ->EndObject() +// ->StartList("empty") +// ->EndList() +// ->EndObject(); +// +// And then the output string would become: +// { +// "name": "value", +// "emptystring": "", +// "nested": { +// "light": "299792458", +// "pi": 3.141592653589793 +// }, +// "empty": [] +// } +// +// JsonObjectWriter does not validate if calls actually result in valid JSON. +// For example, passing an empty name when one would be required won't result +// in an error, just an invalid output. +// +// Note that all int64 and uint64 are rendered as strings instead of numbers. +// This is because JavaScript parses numbers as 64-bit float thus int64 and +// uint64 would lose precision if rendered as numbers. +// +// JsonObjectWriter is thread-unsafe. +class LIBPROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter { + public: + JsonObjectWriter(StringPiece indent_string, + google::protobuf::io::CodedOutputStream* out) + : element_(new Element(NULL)), + stream_(out), sink_(out), + indent_string_(indent_string.ToString()) { + } + virtual ~JsonObjectWriter(); + + // ObjectWriter methods. + virtual JsonObjectWriter* StartObject(StringPiece name); + virtual JsonObjectWriter* EndObject(); + virtual JsonObjectWriter* StartList(StringPiece name); + virtual JsonObjectWriter* EndList(); + virtual JsonObjectWriter* RenderBool(StringPiece name, bool value); + virtual JsonObjectWriter* RenderInt32(StringPiece name, int32 value); + virtual JsonObjectWriter* RenderUint32(StringPiece name, uint32 value); + virtual JsonObjectWriter* RenderInt64(StringPiece name, int64 value); + virtual JsonObjectWriter* RenderUint64(StringPiece name, uint64 value); + virtual JsonObjectWriter* RenderDouble(StringPiece name, double value); + virtual JsonObjectWriter* RenderFloat(StringPiece name, float value); + virtual JsonObjectWriter* RenderString(StringPiece name, StringPiece value); + virtual JsonObjectWriter* RenderBytes(StringPiece name, StringPiece value); + virtual JsonObjectWriter* RenderNull(StringPiece name); + + protected: + class LIBPROTOBUF_EXPORT Element : public BaseElement { + public: + explicit Element(Element* parent) : BaseElement(parent), is_first_(true) {} + + // Called before each field of the Element is to be processed. + // Returns true if this is the first call (processing the first field). + bool is_first() { + if (is_first_) { + is_first_ = false; + return true; + } + return false; + } + + private: + bool is_first_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(Element); + }; + + virtual Element* element() { return element_.get(); } + + private: + class LIBPROTOBUF_EXPORT ByteSinkWrapper : public strings::ByteSink { + public: + explicit ByteSinkWrapper(google::protobuf::io::CodedOutputStream* stream) + : stream_(stream) {} + virtual ~ByteSinkWrapper() {} + + // ByteSink methods. + virtual void Append(const char* bytes, size_t n) { + stream_->WriteRaw(bytes, n); + } + + private: + google::protobuf::io::CodedOutputStream* stream_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSinkWrapper); + }; + + // Renders a simple value as a string. By default all non-string Render + // methods convert their argument to a string and call this method. This + // method can then be used to render the simple value without escaping it. + JsonObjectWriter* RenderSimple(StringPiece name, const string& value) { + WritePrefix(name); + stream_->WriteString(value); + return this; + } + + // Pushes a new element to the stack. + void Push() { element_.reset(new Element(element_.release())); } + + // Pops an element off of the stack and deletes the popped element. + void Pop() { + bool needs_newline = !element_->is_first(); + element_.reset(element_->pop<Element>()); + if (needs_newline) NewLine(); + } + + // If pretty printing is enabled, this will write a newline to the output, + // followed by optional indentation. Otherwise this method is a noop. + void NewLine() { + if (!indent_string_.empty()) { + WriteChar('\n'); + for (int i = 0; i < element()->level(); i++) { + stream_->WriteString(indent_string_); + } + } + } + + // Writes a prefix. This will write out any pretty printing and + // commas that are required, followed by the name and a ':' if + // the name is not null. + void WritePrefix(StringPiece name); + + // Writes an individual character to the output. + void WriteChar(const char c) { stream_->WriteRaw(&c, sizeof(c)); } + + google::protobuf::scoped_ptr<Element> element_; + google::protobuf::io::CodedOutputStream* stream_; + ByteSinkWrapper sink_; + const string indent_string_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_OBJECTWRITER_H__ diff --git a/src/google/protobuf/util/internal/json_objectwriter_test.cc b/src/google/protobuf/util/internal/json_objectwriter_test.cc new file mode 100644 index 00000000..df9a133e --- /dev/null +++ b/src/google/protobuf/util/internal/json_objectwriter_test.cc @@ -0,0 +1,285 @@ +// 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/util/internal/json_objectwriter.h> + +#include <google/protobuf/io/zero_copy_stream_impl_lite.h> +#include <google/protobuf/util/internal/utility.h> +#include <gtest/gtest.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +using google::protobuf::io::CodedOutputStream; +using google::protobuf::io::StringOutputStream; + +class JsonObjectWriterTest : public ::testing::Test { + protected: + JsonObjectWriterTest() + : str_stream_(new StringOutputStream(&output_)), + out_stream_(new CodedOutputStream(str_stream_)), + ow_(NULL) {} + + virtual ~JsonObjectWriterTest() { + delete ow_; + delete out_stream_; + delete str_stream_; + } + + string output_; + StringOutputStream* const str_stream_; + CodedOutputStream* const out_stream_; + ObjectWriter* ow_; +}; + +TEST_F(JsonObjectWriterTest, EmptyRootObject) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartObject("")->EndObject(); + EXPECT_EQ("{}", output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, EmptyObject) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartObject("") + ->RenderString("test", "value") + ->StartObject("empty") + ->EndObject() + ->EndObject(); + EXPECT_EQ("{\"test\":\"value\",\"empty\":{}}", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, EmptyRootList) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartList("")->EndList(); + EXPECT_EQ("[]", output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, EmptyList) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartObject("") + ->RenderString("test", "value") + ->StartList("empty") + ->EndList() + ->EndObject(); + EXPECT_EQ("{\"test\":\"value\",\"empty\":[]}", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, ObjectInObject) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartObject("") + ->StartObject("nested") + ->RenderString("field", "value") + ->EndObject() + ->EndObject(); + EXPECT_EQ("{\"nested\":{\"field\":\"value\"}}", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, ListInObject) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartObject("") + ->StartList("nested") + ->RenderString("", "value") + ->EndList() + ->EndObject(); + EXPECT_EQ("{\"nested\":[\"value\"]}", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, ObjectInList) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartList("") + ->StartObject("") + ->RenderString("field", "value") + ->EndObject() + ->EndList(); + EXPECT_EQ("[{\"field\":\"value\"}]", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, ListInList) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartList("") + ->StartList("") + ->RenderString("", "value") + ->EndList() + ->EndList(); + EXPECT_EQ("[[\"value\"]]", output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, RenderPrimitives) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartObject("") + ->RenderBool("bool", true) + ->RenderDouble("double", std::numeric_limits<double>::max()) + ->RenderFloat("float", std::numeric_limits<float>::max()) + ->RenderInt32("int", std::numeric_limits<int32>::min()) + ->RenderInt64("long", std::numeric_limits<int64>::min()) + ->RenderBytes("bytes", "abracadabra") + ->RenderString("string", "string") + ->RenderBytes("emptybytes", "") + ->RenderString("emptystring", string()) + ->EndObject(); + EXPECT_EQ( + "{\"bool\":true," + "\"double\":" + ValueAsString<double>(1.7976931348623157e+308) + "," + "\"float\":" + ValueAsString<float>(3.4028235e+38) + "," + "\"int\":-2147483648," + "\"long\":\"-9223372036854775808\"," + "\"bytes\":\"YWJyYWNhZGFicmE=\"," + "\"string\":\"string\"," + "\"emptybytes\":\"\"," + "\"emptystring\":\"\"}", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, BytesEncodesAsWebSafeBase64) { + string s; + s.push_back('\377'); + s.push_back('\357'); + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartObject("")->RenderBytes("bytes", s)->EndObject(); + // Non-web-safe would encode this as "/+8=" + EXPECT_EQ("{\"bytes\":\"_-8=\"}", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, PrettyPrintList) { + ow_ = new JsonObjectWriter(" ", out_stream_); + ow_->StartObject("") + ->StartList("items") + ->RenderString("", "item1") + ->RenderString("", "item2") + ->RenderString("", "item3") + ->EndList() + ->StartList("empty") + ->EndList() + ->EndObject(); + EXPECT_EQ( + "{\n" + " \"items\": [\n" + " \"item1\",\n" + " \"item2\",\n" + " \"item3\"\n" + " ],\n" + " \"empty\": []\n" + "}\n", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, PrettyPrintObject) { + ow_ = new JsonObjectWriter(" ", out_stream_); + ow_->StartObject("") + ->StartObject("items") + ->RenderString("key1", "item1") + ->RenderString("key2", "item2") + ->RenderString("key3", "item3") + ->EndObject() + ->StartObject("empty") + ->EndObject() + ->EndObject(); + EXPECT_EQ( + "{\n" + " \"items\": {\n" + " \"key1\": \"item1\",\n" + " \"key2\": \"item2\",\n" + " \"key3\": \"item3\"\n" + " },\n" + " \"empty\": {}\n" + "}\n", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, PrettyPrintEmptyObjectInEmptyList) { + ow_ = new JsonObjectWriter(" ", out_stream_); + ow_->StartObject("") + ->StartList("list") + ->StartObject("") + ->EndObject() + ->EndList() + ->EndObject(); + EXPECT_EQ( + "{\n" + " \"list\": [\n" + " {}\n" + " ]\n" + "}\n", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, PrettyPrintDoubleIndent) { + ow_ = new JsonObjectWriter(" ", out_stream_); + ow_->StartObject("") + ->RenderBool("bool", true) + ->RenderInt32("int", 42) + ->EndObject(); + EXPECT_EQ( + "{\n" + " \"bool\": true,\n" + " \"int\": 42\n" + "}\n", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, StringsEscapedAndEnclosedInDoubleQuotes) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartObject("")->RenderString("string", "'<>&\\\"\r\n")->EndObject(); + EXPECT_EQ("{\"string\":\"'\\u003c\\u003e&\\\\\\\"\\r\\n\"}", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, Stringification) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartObject("") + ->RenderDouble("double_nan", std::numeric_limits<double>::quiet_NaN()) + ->RenderFloat("float_nan", std::numeric_limits<float>::quiet_NaN()) + ->RenderDouble("double_pos", std::numeric_limits<double>::infinity()) + ->RenderFloat("float_pos", std::numeric_limits<float>::infinity()) + ->RenderDouble("double_neg", -std::numeric_limits<double>::infinity()) + ->RenderFloat("float_neg", -std::numeric_limits<float>::infinity()) + ->EndObject(); + EXPECT_EQ( + "{\"double_nan\":\"NaN\"," + "\"float_nan\":\"NaN\"," + "\"double_pos\":\"Infinity\"," + "\"float_pos\":\"Infinity\"," + "\"double_neg\":\"-Infinity\"," + "\"float_neg\":\"-Infinity\"}", + output_.substr(0, out_stream_->ByteCount())); +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc new file mode 100644 index 00000000..d439a221 --- /dev/null +++ b/src/google/protobuf/util/internal/json_stream_parser.cc @@ -0,0 +1,740 @@ +// 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/util/internal/json_stream_parser.h> + +#include <algorithm> +#include <cctype> +#include <cerrno> +#include <cstdlib> +#include <cstring> +#include <memory> +#ifndef _SHARED_PTR_H +#include <google/protobuf/stubs/shared_ptr.h> +#endif + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/util/internal/object_writer.h> + +namespace google { +namespace protobuf { +namespace util { + +// Allow these symbols to be referenced as util::Status, util::error::* in +// this file. +using util::Status; +namespace error { +using util::error::INTERNAL; +using util::error::INVALID_ARGUMENT; +} // namespace error + +namespace converter { + +// Number of digits in a unicode escape sequence (/uXXXX) +static const int kUnicodeEscapedLength = 6; + +// Length of the true, false, and null literals. +static const int true_len = strlen("true"); +static const int false_len = strlen("false"); +static const int null_len = strlen("null"); + +inline bool IsLetter(char c) { + return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || (c == '_') || + (c == '$'); +} + +inline bool IsAlphanumeric(char c) { + return IsLetter(c) || ('0' <= c && c <= '9'); +} + +static bool ConsumeKey(StringPiece* input, StringPiece* key) { + if (input->empty() || !IsLetter((*input)[0])) return false; + int len = 1; + for (; len < input->size(); ++len) { + if (!IsAlphanumeric((*input)[len])) { + break; + } + } + *key = StringPiece(input->data(), len); + *input = StringPiece(input->data() + len, input->size() - len); + return true; +} + +static bool MatchKey(StringPiece input) { + return !input.empty() && IsLetter(input[0]); +} + +JsonStreamParser::JsonStreamParser(ObjectWriter* ow) + : ow_(ow), + stack_(), + leftover_(), + json_(), + p_(), + key_(), + key_storage_(), + finishing_(false), + parsed_(), + parsed_storage_(), + string_open_(0), + utf8_storage_(), + utf8_length_(0) { + // Initialize the stack with a single value to be parsed. + stack_.push(VALUE); +} + +JsonStreamParser::~JsonStreamParser() {} + +util::Status JsonStreamParser::Parse(StringPiece json) { + return ParseChunk(json); +} + +util::Status JsonStreamParser::FinishParse() { + // If we do not expect anything and there is nothing left to parse we're all + // done. + if (stack_.empty() && leftover_.empty()) { + return util::Status::OK; + } + // Parse the remainder in finishing mode, which reports errors for things like + // unterminated strings or unknown tokens that would normally be retried. + p_ = json_ = StringPiece(leftover_); + finishing_ = true; + util::Status result = RunParser(); + if (result.ok()) { + SkipWhitespace(); + if (!p_.empty()) { + result = ReportFailure("Parsing terminated before end of input."); + } + } + return result; +} + +util::Status JsonStreamParser::ParseChunk(StringPiece chunk) { + // If we have leftovers from a previous chunk, append the new chunk to it and + // create a new StringPiece pointing at the string's data. This could be + // large but we rely on the chunks to be small, assuming they are fragments + // of a Cord. + if (!leftover_.empty()) { + chunk.AppendToString(&leftover_); + p_ = json_ = StringPiece(leftover_); + } else { + p_ = json_ = chunk; + } + + finishing_ = false; + util::Status result = RunParser(); + if (!result.ok()) return result; + + SkipWhitespace(); + if (p_.empty()) { + // If we parsed everything we had, clear the leftover. + leftover_.clear(); + } else { + // If we do not expect anything i.e. stack is empty, and we have non-empty + // string left to parse, we report an error. + if (stack_.empty()) { + return ReportFailure("Parsing terminated before end of input."); + } + // If we expect future data i.e. stack is non-empty, and we have some + // unparsed data left, we save it for later parse. + leftover_ = p_.ToString(); + } + return util::Status::OK; +} + +util::Status JsonStreamParser::RunParser() { + while (!stack_.empty()) { + ParseType type = stack_.top(); + TokenType t = (string_open_ == 0) ? GetNextTokenType() : BEGIN_STRING; + stack_.pop(); + util::Status result; + switch (type) { + case VALUE: + result = ParseValue(t); + break; + + case OBJ_MID: + result = ParseObjectMid(t); + break; + + case ENTRY: + result = ParseEntry(t); + break; + + case ENTRY_MID: + result = ParseEntryMid(t); + break; + + case ARRAY_VALUE: + result = ParseArrayValue(t); + break; + + case ARRAY_MID: + result = ParseArrayMid(t); + break; + + default: + result = util::Status(util::error::INTERNAL, + StrCat("Unknown parse type: ", type)); + break; + } + if (!result.ok()) { + // If we were cancelled, save our state and try again later. + if (!finishing_ && result == util::Status::CANCELLED) { + stack_.push(type); + // If we have a key we still need to render, make sure to save off the + // contents in our own storage. + if (!key_.empty() && key_storage_.empty()) { + key_.AppendToString(&key_storage_); + key_ = StringPiece(key_storage_); + } + result = util::Status::OK; + } + return result; + } + } + return util::Status::OK; +} + +util::Status JsonStreamParser::ParseValue(TokenType type) { + switch (type) { + case BEGIN_OBJECT: + return HandleBeginObject(); + case BEGIN_ARRAY: + return HandleBeginArray(); + case BEGIN_STRING: + return ParseString(); + case BEGIN_NUMBER: + return ParseNumber(); + case BEGIN_TRUE: + return ParseTrue(); + case BEGIN_FALSE: + return ParseFalse(); + case BEGIN_NULL: + return ParseNull(); + case UNKNOWN: + return ReportUnknown("Expected a value."); + default: { + // Special case for having been cut off while parsing, wait for more data. + // This handles things like 'fals' being at the end of the string, we + // don't know if the next char would be e, completing it, or something + // else, making it invalid. + if (!finishing_ && p_.length() < false_len) { + return util::Status::CANCELLED; + } + return ReportFailure("Unexpected token."); + } + } +} + +util::Status JsonStreamParser::ParseString() { + util::Status result = ParseStringHelper(); + if (result.ok()) { + ow_->RenderString(key_, parsed_); + key_.clear(); + parsed_.clear(); + parsed_storage_.clear(); + } + return result; +} + +util::Status JsonStreamParser::ParseStringHelper() { + // If we haven't seen the start quote, grab it and remember it for later. + if (string_open_ == 0) { + string_open_ = *p_.data(); + GOOGLE_DCHECK(string_open_ == '\"' || string_open_ == '\''); + Advance(); + } + // Track where we last copied data from so we can minimize copying. + const char* last = p_.data(); + while (!p_.empty()) { + const char* data = p_.data(); + if (*data == '\\') { + // We're about to handle an escape, copy all bytes from last to data. + if (last < data) { + parsed_storage_.append(last, data - last); + last = data; + } + // If we ran out of string after the \, cancel or report an error + // depending on if we expect more data later. + if (p_.length() == 1) { + if (!finishing_) { + return util::Status::CANCELLED; + } + return ReportFailure("Closing quote expected in string."); + } + // Parse a unicode escape if we found \u in the string. + if (data[1] == 'u') { + util::Status result = ParseUnicodeEscape(); + if (!result.ok()) { + return result; + } + // Move last pointer past the unicode escape and continue. + last = p_.data(); + continue; + } + // Handle the standard set of backslash-escaped characters. + switch (data[1]) { + case 'b': + parsed_storage_.push_back('\b'); + break; + case 'f': + parsed_storage_.push_back('\f'); + break; + case 'n': + parsed_storage_.push_back('\n'); + break; + case 'r': + parsed_storage_.push_back('\r'); + break; + case 't': + parsed_storage_.push_back('\t'); + break; + case 'v': + parsed_storage_.push_back('\v'); + break; + default: + parsed_storage_.push_back(data[1]); + } + // We handled two characters, so advance past them and continue. + p_.remove_prefix(2); + last = p_.data(); + continue; + } + // If we found the closing quote note it, advance past it, and return. + if (*data == string_open_) { + // If we didn't copy anything, reuse the input buffer. + if (parsed_storage_.empty()) { + parsed_ = StringPiece(last, data - last); + } else { + if (last < data) { + parsed_storage_.append(last, data - last); + last = data; + } + parsed_ = StringPiece(parsed_storage_); + } + // Clear the quote char so next time we try to parse a string we'll + // start fresh. + string_open_ = 0; + Advance(); + return util::Status::OK; + } + // Normal character, just advance past it. + Advance(); + } + // If we ran out of characters, copy over what we have so far. + if (last < p_.data()) { + parsed_storage_.append(last, p_.data() - last); + } + // If we didn't find the closing quote but we expect more data, cancel for now + if (!finishing_) { + return util::Status::CANCELLED; + } + // End of string reached without a closing quote, report an error. + string_open_ = 0; + return ReportFailure("Closing quote expected in string."); +} + +// Converts a unicode escaped character to a decimal value stored in a char32 +// for use in UTF8 encoding utility. We assume that str begins with \uhhhh and +// convert that from the hex number to a decimal value. +// +// There are some security exploits with UTF-8 that we should be careful of: +// - http://www.unicode.org/reports/tr36/#UTF-8_Exploit +// - http://sites/intl-eng/design-guide/core-application +util::Status JsonStreamParser::ParseUnicodeEscape() { + if (p_.length() < kUnicodeEscapedLength) { + if (!finishing_) { + return util::Status::CANCELLED; + } + return ReportFailure("Illegal hex string."); + } + GOOGLE_DCHECK_EQ('\\', p_.data()[0]); + GOOGLE_DCHECK_EQ('u', p_.data()[1]); + uint32 code = 0; + for (int i = 2; i < kUnicodeEscapedLength; ++i) { + if (!isxdigit(p_.data()[i])) { + return ReportFailure("Invalid escape sequence."); + } + code = (code << 4) + hex_digit_to_int(p_.data()[i]); + } + char buf[UTFmax]; + int len = EncodeAsUTF8Char(code, buf); + // Advance past the unicode escape. + p_.remove_prefix(kUnicodeEscapedLength); + parsed_storage_.append(buf, len); + return util::Status::OK; +} + +util::Status JsonStreamParser::ParseNumber() { + NumberResult number; + util::Status result = ParseNumberHelper(&number); + if (result.ok()) { + switch (number.type) { + case NumberResult::DOUBLE: + ow_->RenderDouble(key_, number.double_val); + key_.clear(); + break; + + case NumberResult::INT: + ow_->RenderInt64(key_, number.int_val); + key_.clear(); + break; + + case NumberResult::UINT: + ow_->RenderUint64(key_, number.uint_val); + key_.clear(); + break; + + default: + return ReportFailure("Unable to parse number."); + } + } + return result; +} + +util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) { + const char* data = p_.data(); + int length = p_.length(); + + // Look for the first non-numeric character, or the end of the string. + int index = 0; + bool floating = false; + bool negative = data[index] == '-'; + // Find the first character that cannot be part of the number. Along the way + // detect if the number needs to be parsed as a double. + // Note that this restricts numbers to the JSON specification, so for example + // we do not support hex or octal notations. + for (; index < length; ++index) { + char c = data[index]; + if (isdigit(c)) continue; + if (c == '.' || c == 'e' || c == 'E') { + floating = true; + continue; + } + if (c == '+' || c == '-') continue; + // Not a valid number character, break out. + break; + } + + // If the entire input is a valid number, and we may have more content in the + // future, we abort for now and resume when we know more. + if (index == length && !finishing_) { + return util::Status::CANCELLED; + } + + // Create a string containing just the number, so we can use safe_strtoX + string number = p_.substr(0, index).ToString(); + + // Floating point number, parse as a double. + if (floating) { + if (!safe_strtod(number, &result->double_val)) { + return ReportFailure("Unable to parse number."); + } + result->type = NumberResult::DOUBLE; + p_.remove_prefix(index); + return util::Status::OK; + } + + // Positive non-floating point number, parse as a uint64. + if (!negative) { + if (!safe_strtou64(number, &result->uint_val)) { + return ReportFailure("Unable to parse number."); + } + result->type = NumberResult::UINT; + p_.remove_prefix(index); + return util::Status::OK; + } + + // Negative non-floating point number, parse as an int64. + if (!safe_strto64(number, &result->int_val)) { + return ReportFailure("Unable to parse number."); + } + result->type = NumberResult::INT; + p_.remove_prefix(index); + return util::Status::OK; +} + +util::Status JsonStreamParser::HandleBeginObject() { + GOOGLE_DCHECK_EQ('{', *p_.data()); + Advance(); + ow_->StartObject(key_); + key_.clear(); + stack_.push(ENTRY); + return util::Status::OK; +} + +util::Status JsonStreamParser::ParseObjectMid(TokenType type) { + if (type == UNKNOWN) { + return ReportUnknown("Expected , or } after key:value pair."); + } + + // Object is complete, advance past the comma and render the EndObject. + if (type == END_OBJECT) { + Advance(); + ow_->EndObject(); + return util::Status::OK; + } + // Found a comma, advance past it and get ready for an entry. + if (type == VALUE_SEPARATOR) { + Advance(); + stack_.push(ENTRY); + return util::Status::OK; + } + // Illegal token after key:value pair. + return ReportFailure("Expected , or } after key:value pair."); +} + +util::Status JsonStreamParser::ParseEntry(TokenType type) { + if (type == UNKNOWN) { + return ReportUnknown("Expected an object key or }."); + } + + // Close the object and return. This allows for trailing commas. + if (type == END_OBJECT) { + ow_->EndObject(); + Advance(); + return util::Status::OK; + } + + util::Status result; + if (type == BEGIN_STRING) { + // Key is a string (standard JSON), parse it and store the string. + result = ParseStringHelper(); + if (result.ok()) { + key_storage_.clear(); + if (!parsed_storage_.empty()) { + parsed_storage_.swap(key_storage_); + key_ = StringPiece(key_storage_); + } else { + key_ = parsed_; + } + parsed_.clear(); + } + } else if (type == BEGIN_KEY) { + // Key is a bare key (back compat), create a StringPiece pointing to it. + result = ParseKey(); + } else { + // Unknown key type, report an error. + result = ReportFailure("Expected an object key or }."); + } + // On success we next expect an entry mid ':' then an object mid ',' or '}' + if (result.ok()) { + stack_.push(OBJ_MID); + stack_.push(ENTRY_MID); + } + return result; +} + +util::Status JsonStreamParser::ParseEntryMid(TokenType type) { + if (type == UNKNOWN) { + return ReportUnknown("Expected : between key:value pair."); + } + if (type == ENTRY_SEPARATOR) { + Advance(); + stack_.push(VALUE); + return util::Status::OK; + } + return ReportFailure("Expected : between key:value pair."); +} + +util::Status JsonStreamParser::HandleBeginArray() { + GOOGLE_DCHECK_EQ('[', *p_.data()); + Advance(); + ow_->StartList(key_); + key_.clear(); + stack_.push(ARRAY_VALUE); + return util::Status::OK; +} + +util::Status JsonStreamParser::ParseArrayValue(TokenType type) { + if (type == UNKNOWN) { + return ReportUnknown("Expected a value or ] within an array."); + } + + if (type == END_ARRAY) { + ow_->EndList(); + Advance(); + return util::Status::OK; + } + + // The ParseValue call may push something onto the stack so we need to make + // sure an ARRAY_MID is after it, so we push it on now. + stack_.push(ARRAY_MID); + util::Status result = ParseValue(type); + if (result == util::Status::CANCELLED) { + // If we were cancelled, pop back off the ARRAY_MID so we don't try to + // push it on again when we try over. + stack_.pop(); + } + return result; +} + +util::Status JsonStreamParser::ParseArrayMid(TokenType type) { + if (type == UNKNOWN) { + return ReportUnknown("Expected , or ] after array value."); + } + + if (type == END_ARRAY) { + ow_->EndList(); + Advance(); + return util::Status::OK; + } + + // Found a comma, advance past it and expect an array value next. + if (type == VALUE_SEPARATOR) { + Advance(); + stack_.push(ARRAY_VALUE); + return util::Status::OK; + } + // Illegal token after array value. + return ReportFailure("Expected , or ] after array value."); +} + +util::Status JsonStreamParser::ParseTrue() { + ow_->RenderBool(key_, true); + key_.clear(); + p_.remove_prefix(true_len); + return util::Status::OK; +} + +util::Status JsonStreamParser::ParseFalse() { + ow_->RenderBool(key_, false); + key_.clear(); + p_.remove_prefix(false_len); + return util::Status::OK; +} + +util::Status JsonStreamParser::ParseNull() { + ow_->RenderNull(key_); + key_.clear(); + p_.remove_prefix(null_len); + return util::Status::OK; +} + +util::Status JsonStreamParser::ReportFailure(StringPiece message) { + static const int kContextLength = 20; + const char* p_start = p_.data(); + const char* json_start = json_.data(); + const char* begin = max(p_start - kContextLength, json_start); + const char* end = min(p_start + kContextLength, json_start + json_.size()); + StringPiece segment(begin, end - begin); + string location(p_start - begin, ' '); + location.push_back('^'); + return util::Status(util::error::INVALID_ARGUMENT, + StrCat(message, "\n", segment, "\n", location)); +} + +util::Status JsonStreamParser::ReportUnknown(StringPiece message) { + // If we aren't finishing the parse, cancel parsing and try later. + if (!finishing_) { + return util::Status::CANCELLED; + } + if (p_.empty()) { + return ReportFailure(StrCat("Unexpected end of string. ", message)); + } + return ReportFailure(message); +} + +void JsonStreamParser::SkipWhitespace() { + while (!p_.empty() && ascii_isspace(*p_.data())) { + Advance(); + } +} + +void JsonStreamParser::Advance() { + // Advance by moving one UTF8 character while making sure we don't go beyond + // the length of StringPiece. + p_.remove_prefix( + min<int>(p_.length(), UTF8FirstLetterNumBytes(p_.data(), p_.length()))); +} + +util::Status JsonStreamParser::ParseKey() { + StringPiece original = p_; + if (!ConsumeKey(&p_, &key_)) { + return ReportFailure("Invalid key or variable name."); + } + // If we consumed everything but expect more data, reset p_ and cancel since + // we can't know if the key was complete or not. + if (!finishing_ && p_.empty()) { + p_ = original; + return util::Status::CANCELLED; + } + // Since we aren't using the key storage, clear it out. + key_storage_.clear(); + return util::Status::OK; +} + +JsonStreamParser::TokenType JsonStreamParser::GetNextTokenType() { + SkipWhitespace(); + + int size = p_.size(); + if (size == 0) { + // If we ran out of data, report unknown and we'll place the previous parse + // type onto the stack and try again when we have more data. + return UNKNOWN; + } + // TODO(sven): Split this method based on context since different contexts + // support different tokens. Would slightly speed up processing? + const char* data = p_.data(); + if (*data == '\"' || *data == '\'') return BEGIN_STRING; + if (*data == '-' || ('0' <= *data && *data <= '9')) { + return BEGIN_NUMBER; + } + if (size >= true_len && !strncmp(data, "true", true_len)) { + return BEGIN_TRUE; + } + if (size >= false_len && !strncmp(data, "false", false_len)) { + return BEGIN_FALSE; + } + if (size >= null_len && !strncmp(data, "null", null_len)) { + return BEGIN_NULL; + } + if (*data == '{') return BEGIN_OBJECT; + if (*data == '}') return END_OBJECT; + if (*data == '[') return BEGIN_ARRAY; + if (*data == ']') return END_ARRAY; + if (*data == ':') return ENTRY_SEPARATOR; + if (*data == ',') return VALUE_SEPARATOR; + if (MatchKey(p_)) { + return BEGIN_KEY; + } + + // We don't know that we necessarily have an invalid token here, just that we + // can't parse what we have so far. So we don't report an error and just + // return UNKNOWN so we can try again later when we have more data, or if we + // finish and we have leftovers. + return UNKNOWN; +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/json_stream_parser.h b/src/google/protobuf/util/internal/json_stream_parser.h new file mode 100644 index 00000000..17b094ae --- /dev/null +++ b/src/google/protobuf/util/internal/json_stream_parser.h @@ -0,0 +1,256 @@ +// 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_UTIL_CONVERTER_JSON_STREAM_PARSER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_STREAM_PARSER_H__ + +#include <stack> +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/stringpiece.h> +#include <google/protobuf/stubs/status.h> + +namespace google { +namespace util { +class Status; +} // namespace util + +namespace protobuf { +namespace util { +namespace converter { + +class ObjectWriter; + +// A JSON parser that can parse a stream of JSON chunks rather than needing the +// entire JSON string up front. It is a modified version of the parser in +// //net/proto/json/json-parser.h that has been changed in the following ways: +// - Changed from recursion to an explicit stack to allow resumption +// - Added support for int64 and uint64 numbers +// - Removed support for octal and decimal escapes +// - Removed support for numeric keys +// - Removed support for functions (javascript) +// - Removed some lax-comma support (but kept trailing comma support) +// - Writes directly to an ObjectWriter rather than using subclassing +// +// Here is an example usage: +// JsonStreamParser parser(ow_.get()); +// util::Status result = parser.Parse(chunk1); +// result.Update(parser.Parse(chunk2)); +// result.Update(parser.FinishParse()); +// GOOGLE_DCHECK(result.ok()) << "Failed to parse JSON"; +// +// This parser is thread-compatible as long as only one thread is calling a +// Parse() method at a time. +class LIBPROTOBUF_EXPORT JsonStreamParser { + public: + // Creates a JsonStreamParser that will write to the given ObjectWriter. + explicit JsonStreamParser(ObjectWriter* ow); + virtual ~JsonStreamParser(); + + // Parse a JSON string (UTF-8 encoded). + util::Status Parse(StringPiece json); + + // Finish parsing the JSON string. + util::Status FinishParse(); + + private: + enum TokenType { + BEGIN_STRING, // " or ' + BEGIN_NUMBER, // - or digit + BEGIN_TRUE, // true + BEGIN_FALSE, // false + BEGIN_NULL, // null + BEGIN_OBJECT, // { + END_OBJECT, // } + BEGIN_ARRAY, // [ + END_ARRAY, // ] + ENTRY_SEPARATOR, // : + VALUE_SEPARATOR, // , + BEGIN_KEY, // letter, _, $ or digit. Must begin with non-digit + UNKNOWN // Unknown token or we ran out of the stream. + }; + + enum ParseType { + VALUE, // Expects a {, [, true, false, null, string or number + OBJ_MID, // Expects a ',' or } + ENTRY, // Expects a key or } + ENTRY_MID, // Expects a : + ARRAY_VALUE, // Expects a value or ] + ARRAY_MID // Expects a ',' or ] + }; + + // Holds the result of parsing a number + struct NumberResult { + enum Type { DOUBLE, INT, UINT }; + Type type; + union { + double double_val; + int64 int_val; + uint64 uint_val; + }; + }; + + // Parses a single chunk of JSON, returning an error if the JSON was invalid. + util::Status ParseChunk(StringPiece json); + + // Runs the parser based on stack_ and p_, until the stack is empty or p_ runs + // out of data. If we unexpectedly run out of p_ we push the latest back onto + // the stack and return. + util::Status RunParser(); + + // Parses a value from p_ and writes it to ow_. + // A value may be an object, array, true, false, null, string or number. + util::Status ParseValue(TokenType type); + + // Parses a string and writes it out to the ow_. + util::Status ParseString(); + + // Parses a string, storing the result in parsed_. + util::Status ParseStringHelper(); + + // This function parses unicode escape sequences in strings. It returns an + // error when there's a parsing error, either the size is not the expected + // size or a character is not a hex digit. When it returns str will contain + // what has been successfully parsed so far. + util::Status ParseUnicodeEscape(); + + // Expects p_ to point to a JSON number, writes the number to the writer using + // the appropriate Render method based on the type of number. + util::Status ParseNumber(); + + // Parse a number into a NumberResult, reporting an error if no number could + // be parsed. This method will try to parse into a uint64, int64, or double + // based on whether the number was positive or negative or had a decimal + // component. + util::Status ParseNumberHelper(NumberResult* result); + + // Handles a { during parsing of a value. + util::Status HandleBeginObject(); + + // Parses from the ENTRY state. + util::Status ParseEntry(TokenType type); + + // Parses from the ENTRY_MID state. + util::Status ParseEntryMid(TokenType type); + + // Parses from the OBJ_MID state. + util::Status ParseObjectMid(TokenType type); + + // Handles a [ during parsing of a value. + util::Status HandleBeginArray(); + + // Parses from the ARRAY_VALUE state. + util::Status ParseArrayValue(TokenType type); + + // Parses from the ARRAY_MID state. + util::Status ParseArrayMid(TokenType type); + + // Expects p_ to point to an unquoted literal + util::Status ParseTrue(); + util::Status ParseFalse(); + util::Status ParseNull(); + + // Report a failure as a util::Status. + util::Status ReportFailure(StringPiece message); + + // Report a failure due to an UNKNOWN token type. We check if we hit the + // end of the stream and if we're finishing or not to detect what type of + // status to return in this case. + util::Status ReportUnknown(StringPiece message); + + // Advance p_ past all whitespace or until the end of the string. + void SkipWhitespace(); + + // Advance p_ one UTF-8 character + void Advance(); + + // Expects p_ to point to the beginning of a key. + util::Status ParseKey(); + + // Return the type of the next token at p_. + TokenType GetNextTokenType(); + + // The object writer to write parse events to. + ObjectWriter* ow_; + + // The stack of parsing we still need to do. When the stack runs empty we will + // have parsed a single value from the root (e.g. an object or list). + std::stack<ParseType> stack_; + + // Contains any leftover text from a previous chunk that we weren't able to + // fully parse, for example the start of a key or number. + string leftover_; + + // The current chunk of JSON being parsed. Primarily used for providing + // context during error reporting. + StringPiece json_; + + // A pointer within the current JSON being parsed, used to track location. + StringPiece p_; + + // Stores the last key read, as we separate parsing of keys and values. + StringPiece key_; + + // Storage for key_ if we need to keep ownership, for example between chunks + // or if the key was unescaped from a JSON string. + string key_storage_; + + // True during the FinishParse() call, so we know that any errors are fatal. + // For example an unterminated string will normally result in cancelling and + // trying during the next chunk, but during FinishParse() it is an error. + bool finishing_; + + // String we parsed during a call to ParseStringHelper(). + StringPiece parsed_; + + // Storage for the string we parsed. This may be empty if the string was able + // to be parsed directly from the input. + string parsed_storage_; + + // The character that opened the string, either ' or ". + // A value of 0 indicates that string parsing is not in process. + char string_open_; + + // Storage for utf8-coerced bytes. + google::protobuf::scoped_array<char> utf8_storage_; + + // Length of the storage for utf8-coerced bytes. + int utf8_length_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonStreamParser); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_STREAM_PARSER_H__ diff --git a/src/google/protobuf/util/internal/json_stream_parser_test.cc b/src/google/protobuf/util/internal/json_stream_parser_test.cc new file mode 100644 index 00000000..b0775a2f --- /dev/null +++ b/src/google/protobuf/util/internal/json_stream_parser_test.cc @@ -0,0 +1,702 @@ +// 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/util/internal/json_stream_parser.h> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/time.h> +#include <google/protobuf/util/internal/expecting_objectwriter.h> +#include <google/protobuf/util/internal/object_writer.h> +#include <google/protobuf/stubs/strutil.h> +#include <gtest/gtest.h> +#include <google/protobuf/stubs/status.h> + + +namespace google { +namespace protobuf { +namespace util { +using util::Status; +namespace error { +using util::error::INVALID_ARGUMENT; +} // namespace error +namespace converter { + +using util::Status; + +// Tests for the JSON Stream Parser. These tests are intended to be +// comprehensive and cover the following: +// +// Positive tests: +// - true, false, null +// - empty object or array. +// - negative and positive double and int, unsigned int +// - single and double quoted strings +// - string key, unquoted key, numeric key +// - array containing array, object, value +// - object containing array, object, value +// - unicode handling in strings +// - ascii escaping (\b, \f, \n, \r, \t, \v) +// - trailing commas +// +// Negative tests: +// - illegal literals +// - mismatched quotes failure on strings +// - unterminated string failure +// - unexpected end of string failure +// - mismatched object and array closing +// - Failure to close array or object +// - numbers too large +// - invalid unicode escapes. +// - invalid unicode sequences. +// - numbers as keys +// +// For each test we split the input string on every possible character to ensure +// the parser is able to handle arbitrarily split input for all cases. We also +// do a final test of the entire test case one character at a time. +class JsonStreamParserTest : public ::testing::Test { + protected: + JsonStreamParserTest() : mock_(), ow_(&mock_) {} + virtual ~JsonStreamParserTest() {} + + util::Status RunTest(StringPiece json, int split) { + JsonStreamParser parser(&mock_); + + // Special case for split == length, test parsing one character at a time. + if (split == json.length()) { + GOOGLE_LOG(INFO) << "Testing split every char: " << json; + for (int i = 0; i < json.length(); ++i) { + StringPiece single = json.substr(i, 1); + util::Status result = parser.Parse(single); + if (!result.ok()) { + return result; + } + } + return parser.FinishParse(); + } + + // Normal case, split at the split point and parse two substrings. + StringPiece first = json.substr(0, split); + StringPiece rest = json.substr(split); + GOOGLE_LOG(INFO) << "Testing split: " << first << "><" << rest; + util::Status result = parser.Parse(first); + if (result.ok()) { + result = parser.Parse(rest); + if (result.ok()) { + result = parser.FinishParse(); + } + } + return result; + } + + void DoTest(StringPiece json, int split) { + util::Status result = RunTest(json, split); + if (!result.ok()) { + GOOGLE_LOG(WARNING) << result; + } + EXPECT_OK(result); + } + + void DoErrorTest(StringPiece json, int split, StringPiece error_prefix) { + util::Status result = RunTest(json, split); + EXPECT_EQ(util::error::INVALID_ARGUMENT, result.error_code()); + StringPiece error_message(result.error_message()); + EXPECT_EQ(error_prefix, error_message.substr(0, error_prefix.size())); + } + + + MockObjectWriter mock_; + ExpectingObjectWriter ow_; +}; + + +// Positive tests + +// - true, false, null +TEST_F(JsonStreamParserTest, SimpleTrue) { + StringPiece str = "true"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderBool("", true); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, SimpleFalse) { + StringPiece str = "false"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderBool("", false); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, SimpleNull) { + StringPiece str = "null"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderNull(""); + DoTest(str, i); + } +} + +// - empty object and array. +TEST_F(JsonStreamParserTest, EmptyObject) { + StringPiece str = "{}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject("")->EndObject(); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, EmptyList) { + StringPiece str = "[]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList("")->EndList(); + DoTest(str, i); + } +} + +// - negative and positive double and int, unsigned int +TEST_F(JsonStreamParserTest, SimpleDouble) { + StringPiece str = "42.5"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderDouble("", 42.5); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, ScientificDouble) { + StringPiece str = "1.2345e-10"; + for (int i = 0; i < str.length(); ++i) { + ow_.RenderDouble("", 1.2345e-10); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, SimpleNegativeDouble) { + StringPiece str = "-1045.235"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderDouble("", -1045.235); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, SimpleInt) { + StringPiece str = "123456"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderUint64("", 123456); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, SimpleNegativeInt) { + StringPiece str = "-79497823553162765"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderInt64("", -79497823553162765LL); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, SimpleUnsignedInt) { + StringPiece str = "11779497823553162765"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderUint64("", 11779497823553162765ULL); + DoTest(str, i); + } +} + +// - single and double quoted strings +TEST_F(JsonStreamParserTest, EmptyDoubleQuotedString) { + StringPiece str = "\"\""; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderString("", ""); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, EmptySingleQuotedString) { + StringPiece str = "''"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderString("", ""); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, SimpleDoubleQuotedString) { + StringPiece str = "\"Some String\""; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderString("", "Some String"); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, SimpleSingleQuotedString) { + StringPiece str = "'Another String'"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderString("", "Another String"); + DoTest(str, i); + } +} + +// - string key, unquoted key, numeric key +TEST_F(JsonStreamParserTest, ObjectKeyTypes) { + StringPiece str = + "{'s': true, \"d\": false, key: null, snake_key: [], camelKey: {}}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject("") + ->RenderBool("s", true) + ->RenderBool("d", false) + ->RenderNull("key") + ->StartList("snake_key") + ->EndList() + ->StartObject("camelKey") + ->EndObject() + ->EndObject(); + DoTest(str, i); + } +} + +// - array containing array, object, values (true, false, null, num, string) +TEST_F(JsonStreamParserTest, ArrayValues) { + StringPiece str = + "[true, false, null, 'a string', \"another string\", [22, -127, 45.3, " + "-1056.4, 11779497823553162765], {'key': true}]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList("") + ->RenderBool("", true) + ->RenderBool("", false) + ->RenderNull("") + ->RenderString("", "a string") + ->RenderString("", "another string") + ->StartList("") + ->RenderUint64("", 22) + ->RenderInt64("", -127) + ->RenderDouble("", 45.3) + ->RenderDouble("", -1056.4) + ->RenderUint64("", 11779497823553162765ULL) + ->EndList() + ->StartObject("") + ->RenderBool("key", true) + ->EndObject() + ->EndList(); + DoTest(str, i); + } +} + +// - object containing array, object, value (true, false, null, num, string) +TEST_F(JsonStreamParserTest, ObjectValues) { + StringPiece str = + "{t: true, f: false, n: null, s: 'a string', d: \"another string\", pi: " + "22, ni: -127, pd: 45.3, nd: -1056.4, pl: 11779497823553162765, l: [[]], " + "o: {'key': true}}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject("") + ->RenderBool("t", true) + ->RenderBool("f", false) + ->RenderNull("n") + ->RenderString("s", "a string") + ->RenderString("d", "another string") + ->RenderUint64("pi", 22) + ->RenderInt64("ni", -127) + ->RenderDouble("pd", 45.3) + ->RenderDouble("nd", -1056.4) + ->RenderUint64("pl", 11779497823553162765ULL) + ->StartList("l") + ->StartList("") + ->EndList() + ->EndList() + ->StartObject("o") + ->RenderBool("key", true) + ->EndObject() + ->EndObject(); + DoTest(str, i); + } +} + +#ifndef _MSC_VER +// - unicode handling in strings +TEST_F(JsonStreamParserTest, UnicodeEscaping) { + StringPiece str = "[\"\\u0639\\u0631\\u0628\\u0649\"]"; + for (int i = 0; i <= str.length(); ++i) { + // TODO(xiaofeng): Figure out what default encoding to use for JSON strings. + // In protobuf we use UTF-8 for strings, but for JSON we probably should allow + // different encodings? + ow_.StartList("")->RenderString("", "\u0639\u0631\u0628\u0649")->EndList(); + DoTest(str, i); + } +} +#endif + +// - ascii escaping (\b, \f, \n, \r, \t, \v) +TEST_F(JsonStreamParserTest, AsciiEscaping) { + StringPiece str = + "[\"\\b\", \"\\ning\", \"test\\f\", \"\\r\\t\", \"test\\\\\\ving\"]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList("") + ->RenderString("", "\b") + ->RenderString("", "\ning") + ->RenderString("", "test\f") + ->RenderString("", "\r\t") + ->RenderString("", "test\\\ving") + ->EndList(); + DoTest(str, i); + } +} + +// - trailing commas, we support a single trailing comma but no internal commas. +TEST_F(JsonStreamParserTest, TrailingCommas) { + StringPiece str = "[['a',true,], {b: null,},]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList("") + ->StartList("") + ->RenderString("", "a") + ->RenderBool("", true) + ->EndList() + ->StartObject("") + ->RenderNull("b") + ->EndObject() + ->EndList(); + DoTest(str, i); + } +} + +// Negative tests + +// illegal literals +TEST_F(JsonStreamParserTest, ExtraTextAfterTrue) { + StringPiece str = "truee"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderBool("", true); + DoErrorTest(str, i, "Parsing terminated before end of input."); + } +} + +TEST_F(JsonStreamParserTest, InvalidNumberDashOnly) { + StringPiece str = "-"; + for (int i = 0; i <= str.length(); ++i) { + DoErrorTest(str, i, "Unable to parse number."); + } +} + +TEST_F(JsonStreamParserTest, InvalidNumberDashName) { + StringPiece str = "-foo"; + for (int i = 0; i <= str.length(); ++i) { + DoErrorTest(str, i, "Unable to parse number."); + } +} + +TEST_F(JsonStreamParserTest, InvalidLiteralInArray) { + StringPiece str = "[nule]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList(""); + DoErrorTest(str, i, "Unexpected token."); + } +} + +TEST_F(JsonStreamParserTest, InvalidLiteralInObject) { + StringPiece str = "{123false}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Expected an object key or }."); + } +} + +// mismatched quotes failure on strings +TEST_F(JsonStreamParserTest, MismatchedSingleQuotedLiteral) { + StringPiece str = "'Some str\""; + for (int i = 0; i <= str.length(); ++i) { + DoErrorTest(str, i, "Closing quote expected in string."); + } +} + +TEST_F(JsonStreamParserTest, MismatchedDoubleQuotedLiteral) { + StringPiece str = "\"Another string that ends poorly!'"; + for (int i = 0; i <= str.length(); ++i) { + DoErrorTest(str, i, "Closing quote expected in string."); + } +} + +// unterminated strings +TEST_F(JsonStreamParserTest, UnterminatedLiteralString) { + StringPiece str = "\"Forgot the rest of i"; + for (int i = 0; i <= str.length(); ++i) { + DoErrorTest(str, i, "Closing quote expected in string."); + } +} + +TEST_F(JsonStreamParserTest, UnterminatedStringEscape) { + StringPiece str = "\"Forgot the rest of \\"; + for (int i = 0; i <= str.length(); ++i) { + DoErrorTest(str, i, "Closing quote expected in string."); + } +} + +TEST_F(JsonStreamParserTest, UnterminatedStringInArray) { + StringPiece str = "[\"Forgot to close the string]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList(""); + DoErrorTest(str, i, "Closing quote expected in string."); + } +} + +TEST_F(JsonStreamParserTest, UnterminatedStringInObject) { + StringPiece str = "{f: \"Forgot to close the string}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Closing quote expected in string."); + } +} + +TEST_F(JsonStreamParserTest, UnterminatedObject) { + StringPiece str = "{"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Unexpected end of string."); + } +} + + +// mismatched object and array closing +TEST_F(JsonStreamParserTest, MismatchedCloseObject) { + StringPiece str = "{'key': true]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject("")->RenderBool("key", true); + DoErrorTest(str, i, "Expected , or } after key:value pair."); + } +} + +TEST_F(JsonStreamParserTest, MismatchedCloseArray) { + StringPiece str = "[true, null}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList("")->RenderBool("", true)->RenderNull(""); + DoErrorTest(str, i, "Expected , or ] after array value."); + } +} + +// Invalid object keys. +TEST_F(JsonStreamParserTest, InvalidNumericObjectKey) { + StringPiece str = "{42: true}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Expected an object key or }."); + } +} + +TEST_F(JsonStreamParserTest, InvalidLiteralObjectInObject) { + StringPiece str = "{{bob: true}}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Expected an object key or }."); + } +} + +TEST_F(JsonStreamParserTest, InvalidLiteralArrayInObject) { + StringPiece str = "{[null]}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Expected an object key or }."); + } +} + +TEST_F(JsonStreamParserTest, InvalidLiteralValueInObject) { + StringPiece str = "{false}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Expected an object key or }."); + } +} + +TEST_F(JsonStreamParserTest, MissingColonAfterStringInObject) { + StringPiece str = "{\"key\"}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Expected : between key:value pair."); + } +} + +TEST_F(JsonStreamParserTest, MissingColonAfterKeyInObject) { + StringPiece str = "{key}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Expected : between key:value pair."); + } +} + +TEST_F(JsonStreamParserTest, EndOfTextAfterKeyInObject) { + StringPiece str = "{key"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Unexpected end of string."); + } +} + +TEST_F(JsonStreamParserTest, MissingValueAfterColonInObject) { + StringPiece str = "{key:}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Unexpected token."); + } +} + +TEST_F(JsonStreamParserTest, MissingCommaBetweenObjectEntries) { + StringPiece str = "{key:20 'hello': true}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject("")->RenderUint64("key", 20); + DoErrorTest(str, i, "Expected , or } after key:value pair."); + } +} + +TEST_F(JsonStreamParserTest, InvalidLiteralAsObjectKey) { + StringPiece str = "{false: 20}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Expected an object key or }."); + } +} + +TEST_F(JsonStreamParserTest, ExtraCharactersAfterObject) { + StringPiece str = "{}}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject("")->EndObject(); + DoErrorTest(str, i, "Parsing terminated before end of input."); + } +} + +// numbers too large +TEST_F(JsonStreamParserTest, PositiveNumberTooBig) { + StringPiece str = "[18446744073709551616]"; // 2^64 + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList(""); + DoErrorTest(str, i, "Unable to parse number."); + } +} + +TEST_F(JsonStreamParserTest, NegativeNumberTooBig) { + StringPiece str = "[-18446744073709551616]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList(""); + DoErrorTest(str, i, "Unable to parse number."); + } +} + +/* +TODO(sven): Fail parsing when parsing a double that is too large. + +TEST_F(JsonStreamParserTest, DoubleTooBig) { + StringPiece str = "[184464073709551232321616.45]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList(""); + DoErrorTest(str, i, "Unable to parse number"); + } +} +*/ + +// invalid unicode sequence. +TEST_F(JsonStreamParserTest, UnicodeEscapeCutOff) { + StringPiece str = "\"\\u12"; + for (int i = 0; i <= str.length(); ++i) { + DoErrorTest(str, i, "Illegal hex string."); + } +} + +TEST_F(JsonStreamParserTest, UnicodeEscapeInvalidCharacters) { + StringPiece str = "\"\\u12$4hello"; + for (int i = 0; i <= str.length(); ++i) { + DoErrorTest(str, i, "Invalid escape sequence."); + } +} + +// Extra commas with an object or array. +TEST_F(JsonStreamParserTest, ExtraCommaInObject) { + StringPiece str = "{'k1': true,,'k2': false}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject("")->RenderBool("k1", true); + DoErrorTest(str, i, "Expected an object key or }."); + } +} + +TEST_F(JsonStreamParserTest, ExtraCommaInArray) { + StringPiece str = "[true,,false}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList("")->RenderBool("", true); + DoErrorTest(str, i, "Unexpected token."); + } +} + +// Extra text beyond end of value. +TEST_F(JsonStreamParserTest, ExtraTextAfterLiteral) { + StringPiece str = "'hello', 'world'"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderString("", "hello"); + DoErrorTest(str, i, "Parsing terminated before end of input."); + } +} + +TEST_F(JsonStreamParserTest, ExtraTextAfterObject) { + StringPiece str = "{'key': true} 'oops'"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject("")->RenderBool("key", true)->EndObject(); + DoErrorTest(str, i, "Parsing terminated before end of input."); + } +} + +TEST_F(JsonStreamParserTest, ExtraTextAfterArray) { + StringPiece str = "[null] 'oops'"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList("")->RenderNull("")->EndList(); + DoErrorTest(str, i, "Parsing terminated before end of input."); + } +} + +// Random unknown text in the value. +TEST_F(JsonStreamParserTest, UnknownCharactersAsValue) { + StringPiece str = "*"; + for (int i = 0; i <= str.length(); ++i) { + DoErrorTest(str, i, "Expected a value."); + } +} + +TEST_F(JsonStreamParserTest, UnknownCharactersInArray) { + StringPiece str = "[*]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList(""); + DoErrorTest(str, i, "Expected a value or ] within an array."); + } +} + +TEST_F(JsonStreamParserTest, UnknownCharactersInObject) { + StringPiece str = "{'key': *}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Expected a value."); + } +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/location_tracker.h b/src/google/protobuf/util/internal/location_tracker.h new file mode 100644 index 00000000..0864b057 --- /dev/null +++ b/src/google/protobuf/util/internal/location_tracker.h @@ -0,0 +1,65 @@ +// 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_UTIL_CONVERTER_LOCATION_TRACKER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_LOCATION_TRACKER_H__ + +#include <string> + +#include <google/protobuf/stubs/common.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// LocationTrackerInterface is an interface for classes that track +// the location information for the purpose of error reporting. +class LIBPROTOBUF_EXPORT LocationTrackerInterface { + public: + virtual ~LocationTrackerInterface() {} + + // Returns the object location as human readable string. + virtual string ToString() const = 0; + + protected: + LocationTrackerInterface() {} + + private: + // Please do not add any data members to this class. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LocationTrackerInterface); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_LOCATION_TRACKER_H__ diff --git a/src/google/protobuf/util/internal/mock_error_listener.h b/src/google/protobuf/util/internal/mock_error_listener.h new file mode 100644 index 00000000..591c35db --- /dev/null +++ b/src/google/protobuf/util/internal/mock_error_listener.h @@ -0,0 +1,63 @@ +// 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_UTIL_CONVERTER_MOCK_ERROR_LISTENER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_MOCK_ERROR_LISTENER_H__ + +#include <google/protobuf/stubs/stringpiece.h> +#include <google/protobuf/util/internal/error_listener.h> +#include <google/protobuf/util/internal/location_tracker.h> +#include <gmock/gmock.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +class MockErrorListener : public ErrorListener { + public: + MockErrorListener() {} + virtual ~MockErrorListener() {} + + MOCK_METHOD3(InvalidName, void(const LocationTrackerInterface& loc, + StringPiece unknown_name, + StringPiece message)); + MOCK_METHOD3(InvalidValue, void(const LocationTrackerInterface& loc, + StringPiece type_name, StringPiece value)); + MOCK_METHOD2(MissingField, void(const LocationTrackerInterface& loc, + StringPiece missing_name)); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_MOCK_ERROR_LISTENER_H__ diff --git a/src/google/protobuf/util/internal/object_location_tracker.h b/src/google/protobuf/util/internal/object_location_tracker.h new file mode 100644 index 00000000..8586cecc --- /dev/null +++ b/src/google/protobuf/util/internal/object_location_tracker.h @@ -0,0 +1,64 @@ +// 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_UTIL_CONVERTER_OBJECT_LOCATION_TRACKER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_LOCATION_TRACKER_H__ + +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/util/internal/location_tracker.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// An empty concrete implementation of LocationTrackerInterface. +class ObjectLocationTracker : public LocationTrackerInterface { + public: + // Creates an empty location tracker. + ObjectLocationTracker() {} + + virtual ~ObjectLocationTracker() {} + + // Returns empty because nothing is tracked. + virtual string ToString() const { return ""; } + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectLocationTracker); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_LOCATION_TRACKER_H__ diff --git a/src/google/protobuf/util/internal/object_source.h b/src/google/protobuf/util/internal/object_source.h new file mode 100644 index 00000000..2c31cfb0 --- /dev/null +++ b/src/google/protobuf/util/internal/object_source.h @@ -0,0 +1,79 @@ +// 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_UTIL_CONVERTER_OBJECT_SOURCE_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_SOURCE_H__ + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/stringpiece.h> +#include <google/protobuf/stubs/status.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +class ObjectWriter; + +// An ObjectSource is anything that can write to an ObjectWriter. +// Implementation of this interface typically provide constructors or +// factory methods to create an instance based on some source data, for +// example, a character stream, or protobuf. +// +// Derived classes could be thread-unsafe. +class LIBPROTOBUF_EXPORT ObjectSource { + public: + virtual ~ObjectSource() {} + + // Writes to the ObjectWriter + virtual util::Status WriteTo(ObjectWriter* ow) const { + return NamedWriteTo("", ow); + } + + // Writes to the ObjectWriter with a custom name for the message. + // This is useful when you chain ObjectSource together by embedding one + // within another. + virtual util::Status NamedWriteTo(StringPiece name, + ObjectWriter* ow) const = 0; + + protected: + ObjectSource() {} + + private: + // Do not add any data members to this class. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectSource); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_SOURCE_H__ diff --git a/src/google/protobuf/util/internal/object_writer.cc b/src/google/protobuf/util/internal/object_writer.cc new file mode 100644 index 00000000..57cc08a1 --- /dev/null +++ b/src/google/protobuf/util/internal/object_writer.cc @@ -0,0 +1,92 @@ +// 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/util/internal/object_writer.h> + +#include <google/protobuf/util/internal/datapiece.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// static +void ObjectWriter::RenderDataPieceTo(const DataPiece& data, StringPiece name, + ObjectWriter* ow) { + switch (data.type()) { + case DataPiece::TYPE_INT32: { + ow->RenderInt32(name, data.ToInt32().ValueOrDie()); + break; + } + case DataPiece::TYPE_INT64: { + ow->RenderInt64(name, data.ToInt64().ValueOrDie()); + break; + } + case DataPiece::TYPE_UINT32: { + ow->RenderUint32(name, data.ToUint32().ValueOrDie()); + break; + } + case DataPiece::TYPE_UINT64: { + ow->RenderUint64(name, data.ToUint64().ValueOrDie()); + break; + } + case DataPiece::TYPE_DOUBLE: { + ow->RenderDouble(name, data.ToDouble().ValueOrDie()); + break; + } + case DataPiece::TYPE_FLOAT: { + ow->RenderFloat(name, data.ToFloat().ValueOrDie()); + break; + } + case DataPiece::TYPE_BOOL: { + ow->RenderBool(name, data.ToBool().ValueOrDie()); + break; + } + case DataPiece::TYPE_STRING: { + ow->RenderString(name, data.ToString().ValueOrDie()); + break; + } + case DataPiece::TYPE_BYTES: { + ow->RenderBytes(name, data.ToBytes().ValueOrDie()); + break; + } + case DataPiece::TYPE_NULL: { + ow->RenderNull(name); + break; + } + default: + break; + } +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/object_writer.h b/src/google/protobuf/util/internal/object_writer.h new file mode 100644 index 00000000..20bd3627 --- /dev/null +++ b/src/google/protobuf/util/internal/object_writer.h @@ -0,0 +1,126 @@ +// 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_UTIL_CONVERTER_OBJECT_WRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_WRITER_H__ + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/stringpiece.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +class DataPiece; + +// An ObjectWriter is an interface for writing a stream of events +// representing objects and collections. Implementation of this +// interface can be used to write an object stream to an in-memory +// structure, protobufs, JSON, XML, or any other output format +// desired. The ObjectSource interface is typically used as the +// source of an object stream. +// +// See JsonObjectWriter for a sample implementation of ObjectWriter +// and its use. +// +// Derived classes could be thread-unsafe. +// +// TODO(xinb): seems like a prime candidate to apply the RAII paradigm +// and get rid the need to call EndXXX(). +class LIBPROTOBUF_EXPORT ObjectWriter { + public: + virtual ~ObjectWriter() {} + + // Starts an object. If the name is empty, the object will not be named. + virtual ObjectWriter* StartObject(StringPiece name) = 0; + + // Ends an object. + virtual ObjectWriter* EndObject() = 0; + + // Starts a list. If the name is empty, the list will not be named. + virtual ObjectWriter* StartList(StringPiece name) = 0; + + // Ends a list. + virtual ObjectWriter* EndList() = 0; + + // Renders a boolean value. + virtual ObjectWriter* RenderBool(StringPiece name, bool value) = 0; + + // Renders an 32-bit integer value. + virtual ObjectWriter* RenderInt32(StringPiece name, int32 value) = 0; + + // Renders an 32-bit unsigned integer value. + virtual ObjectWriter* RenderUint32(StringPiece name, uint32 value) = 0; + + // Renders a 64-bit integer value. + virtual ObjectWriter* RenderInt64(StringPiece name, int64 value) = 0; + + // Renders an 64-bit unsigned integer value. + virtual ObjectWriter* RenderUint64(StringPiece name, uint64 value) = 0; + + // Renders a double value. + virtual ObjectWriter* RenderDouble(StringPiece name, double value) = 0; + + // Renders a float value. + virtual ObjectWriter* RenderFloat(StringPiece name, float value) = 0; + + // Renders a StringPiece value. This is for rendering strings. + virtual ObjectWriter* RenderString(StringPiece name, StringPiece value) = 0; + + // Renders a bytes value. + virtual ObjectWriter* RenderBytes(StringPiece name, StringPiece value) = 0; + + // Renders a Null value. + virtual ObjectWriter* RenderNull(StringPiece name) = 0; + + // Disables case normalization. Any RenderTYPE call after calling this + // function will output the name field as-is. No normalization is attempted on + // it. This setting is reset immediately after the next RenderTYPE is called. + virtual ObjectWriter* DisableCaseNormalizationForNextKey() { return this; } + + // Renders a DataPiece object to a ObjectWriter. + static void RenderDataPieceTo(const DataPiece& data, StringPiece name, + ObjectWriter* ow); + + protected: + ObjectWriter() {} + + private: + // Do not add any data members to this class. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_WRITER_H__ diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc new file mode 100644 index 00000000..53a0e47a --- /dev/null +++ b/src/google/protobuf/util/internal/protostream_objectsource.cc @@ -0,0 +1,1051 @@ +// 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/util/internal/protostream_objectsource.h> + +#include <utility> + +#include <google/protobuf/stubs/casts.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/stringprintf.h> +#include <google/protobuf/stubs/time.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/wire_format.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/util/internal/field_mask_utility.h> +#include <google/protobuf/util/internal/constants.h> +#include <google/protobuf/util/internal/utility.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/map_util.h> +#include <google/protobuf/stubs/status_macros.h> + + +namespace google { +namespace protobuf { +namespace util { +using util::Status; +using util::StatusOr; +namespace error { +using util::error::Code; +using util::error::INTERNAL; +} +namespace converter { + +using google::protobuf::Descriptor; +using google::protobuf::EnumValueDescriptor; +using google::protobuf::FieldDescriptor; +using google::protobuf::internal::WireFormat; +using google::protobuf::internal::WireFormatLite; +using util::Status; +using util::StatusOr; + +namespace { +// Finds a field with the given number. NULL if none found. +const google::protobuf::Field* FindFieldByNumber( + const google::protobuf::Type& type, int number); + +// Returns true if the field is packable. +bool IsPackable(const google::protobuf::Field& field); + +// Finds an enum value with the given number. NULL if none found. +const google::protobuf::EnumValue* FindEnumValueByNumber( + const google::protobuf::Enum& tech_enum, int number); + +// Utility function to format nanos. +const string FormatNanos(uint32 nanos); +} // namespace + + +ProtoStreamObjectSource::ProtoStreamObjectSource( + google::protobuf::io::CodedInputStream* stream, TypeResolver* type_resolver, + const google::protobuf::Type& type) + : stream_(stream), + typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), + own_typeinfo_(true), + type_(type) { + GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL."; +} + +ProtoStreamObjectSource::ProtoStreamObjectSource( + google::protobuf::io::CodedInputStream* stream, TypeInfo* typeinfo, + const google::protobuf::Type& type) + : stream_(stream), typeinfo_(typeinfo), own_typeinfo_(false), type_(type) { + GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL."; +} + +ProtoStreamObjectSource::~ProtoStreamObjectSource() { + if (own_typeinfo_) { + delete typeinfo_; + } +} + +Status ProtoStreamObjectSource::NamedWriteTo(StringPiece name, + ObjectWriter* ow) const { + return WriteMessage(type_, name, 0, true, ow); +} + +const google::protobuf::Field* ProtoStreamObjectSource::FindAndVerifyField( + const google::protobuf::Type& type, uint32 tag) const { + // Lookup the new field in the type by tag number. + const google::protobuf::Field* field = FindFieldByNumber(type, tag >> 3); + // Verify if the field corresponds to the wire type in tag. + // If there is any discrepancy, mark the field as not found. + if (field != NULL) { + WireFormatLite::WireType expected_type = + WireFormatLite::WireTypeForFieldType( + static_cast<WireFormatLite::FieldType>(field->kind())); + WireFormatLite::WireType actual_type = WireFormatLite::GetTagWireType(tag); + if (actual_type != expected_type && + (!IsPackable(*field) || + actual_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) { + field = NULL; + } + } + return field; +} + +Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type, + StringPiece name, + const uint32 end_tag, + bool include_start_and_end, + ObjectWriter* ow) const { + const TypeRenderer* type_renderer = FindTypeRenderer(type.name()); + if (type_renderer != NULL) { + return (*type_renderer)(this, type, name, ow); + } + + const google::protobuf::Field* field = NULL; + string field_name; + // last_tag set to dummy value that is different from tag. + uint32 tag = stream_->ReadTag(), last_tag = tag + 1; + + if (include_start_and_end) { + ow->StartObject(name); + } + while (tag != end_tag) { + if (tag != last_tag) { // Update field only if tag is changed. + last_tag = tag; + field = FindAndVerifyField(type, tag); + if (field != NULL) { + field_name = field->name(); + } + } + if (field == NULL) { + // If we didn't find a field, skip this unknown tag. + // TODO(wpoon): Check return boolean value. + WireFormat::SkipField(stream_, tag, NULL); + tag = stream_->ReadTag(); + continue; + } + + if (field->cardinality() == + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) { + if (IsMap(*field)) { + ow->StartObject(field_name); + ASSIGN_OR_RETURN(tag, RenderMap(field, field_name, tag, ow)); + ow->EndObject(); + } else { + ASSIGN_OR_RETURN(tag, RenderList(field, field_name, tag, ow)); + } + } else { + // Render the field. + RETURN_IF_ERROR(RenderField(field, field_name, ow)); + tag = stream_->ReadTag(); + } + } + if (include_start_and_end) { + ow->EndObject(); + } + return Status::OK; +} + +StatusOr<uint32> ProtoStreamObjectSource::RenderList( + const google::protobuf::Field* field, StringPiece name, uint32 list_tag, + ObjectWriter* ow) const { + uint32 tag_to_return = 0; + ow->StartList(name); + if (IsPackable(*field) && + list_tag == + WireFormatLite::MakeTag(field->number(), + WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) { + RETURN_IF_ERROR(RenderPacked(field, ow)); + // Since packed fields have a single tag, read another tag from stream to + // return. + tag_to_return = stream_->ReadTag(); + } else { + do { + RETURN_IF_ERROR(RenderField(field, "", ow)); + } while ((tag_to_return = stream_->ReadTag()) == list_tag); + } + ow->EndList(); + return tag_to_return; +} + +StatusOr<uint32> ProtoStreamObjectSource::RenderMap( + const google::protobuf::Field* field, StringPiece name, uint32 list_tag, + ObjectWriter* ow) const { + const google::protobuf::Type* field_type = + typeinfo_->GetType(field->type_url()); + uint32 tag_to_return = 0; + if (IsPackable(*field) && + list_tag == + WireFormatLite::MakeTag(field->number(), + WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) { + RETURN_IF_ERROR(RenderPackedMapEntry(field_type, ow)); + tag_to_return = stream_->ReadTag(); + } else { + do { + RETURN_IF_ERROR(RenderMapEntry(field_type, ow)); + } while ((tag_to_return = stream_->ReadTag()) == list_tag); + } + return tag_to_return; +} + +Status ProtoStreamObjectSource::RenderMapEntry( + const google::protobuf::Type* type, ObjectWriter* ow) const { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); // message length + int old_limit = stream_->PushLimit(buffer32); + string map_key; + for (uint32 tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) { + const google::protobuf::Field* field = FindAndVerifyField(*type, tag); + if (field == NULL) { + WireFormat::SkipField(stream_, tag, NULL); + continue; + } + // Map field numbers are key = 1 and value = 2 + if (field->number() == 1) { + map_key = ReadFieldValueAsString(*field); + } else if (field->number() == 2) { + if (map_key.empty()) { + return Status(util::error::INTERNAL, "Map key must be non-empty"); + } + // Disable case normalization for map keys as they are just data. We + // retain them intact. + ow->DisableCaseNormalizationForNextKey(); + RETURN_IF_ERROR(RenderField(field, map_key, ow)); + } + } + stream_->PopLimit(old_limit); + + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderPacked( + const google::protobuf::Field* field, ObjectWriter* ow) const { + uint32 length; + stream_->ReadVarint32(&length); + int old_limit = stream_->PushLimit(length); + while (stream_->BytesUntilLimit() > 0) { + RETURN_IF_ERROR(RenderField(field, StringPiece(), ow)); + } + stream_->PopLimit(old_limit); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderPackedMapEntry( + const google::protobuf::Type* type, ObjectWriter* ow) const { + uint32 length; + stream_->ReadVarint32(&length); + int old_limit = stream_->PushLimit(length); + while (stream_->BytesUntilLimit() > 0) { + RETURN_IF_ERROR(RenderMapEntry(type, ow)); + } + stream_->PopLimit(old_limit); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderTimestamp( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { + pair<int64, int32> p = os->ReadSecondsAndNanos(type); + int64 seconds = p.first; + int32 nanos = p.second; + if (seconds > kMaxSeconds || seconds < kMinSeconds) { + return Status( + util::error::INTERNAL, + StrCat("Timestamp seconds exceeds limit for field: ", field_name)); + } + + if (nanos < 0 || nanos >= kNanosPerSecond) { + return Status( + util::error::INTERNAL, + StrCat("Timestamp nanos exceeds limit for field: ", field_name)); + } + + ow->RenderString(field_name, + ::google::protobuf::internal::FormatTime(seconds, nanos)); + + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderDuration( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { + pair<int64, int32> p = os->ReadSecondsAndNanos(type); + int64 seconds = p.first; + int32 nanos = p.second; + if (seconds > kMaxSeconds || seconds < kMinSeconds) { + return Status( + util::error::INTERNAL, + StrCat("Duration seconds exceeds limit for field: ", field_name)); + } + + if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) { + return Status( + util::error::INTERNAL, + StrCat("Duration nanos exceeds limit for field: ", field_name)); + } + + string sign = ""; + if (seconds < 0) { + if (nanos > 0) { + return Status(util::error::INTERNAL, + StrCat( + "Duration nanos is non-negative, but seconds is " + "negative for field: ", + field_name)); + } + sign = "-"; + seconds = -seconds; + nanos = -nanos; + } else if (seconds == 0 && nanos < 0) { + sign = "-"; + nanos = -nanos; + } + string formatted_duration = StringPrintf("%s%lld%ss", sign.c_str(), seconds, + FormatNanos(nanos).c_str()); + ow->RenderString(field_name, formatted_duration); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderDouble(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + uint64 buffer64 = 0; // default value of Double wrapper value + if (tag != 0) { + os->stream_->ReadLittleEndian64(&buffer64); + os->stream_->ReadTag(); + } + ow->RenderDouble(field_name, bit_cast<double>(buffer64)); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderFloat(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + uint32 buffer32 = 0; // default value of Float wrapper value + if (tag != 0) { + os->stream_->ReadLittleEndian32(&buffer32); + os->stream_->ReadTag(); + } + ow->RenderFloat(field_name, bit_cast<float>(buffer32)); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderInt64(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + uint64 buffer64 = 0; // default value of Int64 wrapper value + if (tag != 0) { + os->stream_->ReadVarint64(&buffer64); + os->stream_->ReadTag(); + } + ow->RenderInt64(field_name, bit_cast<int64>(buffer64)); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderUInt64(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + uint64 buffer64 = 0; // default value of UInt64 wrapper value + if (tag != 0) { + os->stream_->ReadVarint64(&buffer64); + os->stream_->ReadTag(); + } + ow->RenderUint64(field_name, bit_cast<uint64>(buffer64)); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderInt32(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + uint32 buffer32 = 0; // default value of Int32 wrapper value + if (tag != 0) { + os->stream_->ReadVarint32(&buffer32); + os->stream_->ReadTag(); + } + ow->RenderInt32(field_name, bit_cast<int32>(buffer32)); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderUInt32(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + uint32 buffer32 = 0; // default value of UInt32 wrapper value + if (tag != 0) { + os->stream_->ReadVarint32(&buffer32); + os->stream_->ReadTag(); + } + ow->RenderUint32(field_name, bit_cast<uint32>(buffer32)); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderBool(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + uint64 buffer64 = 0; // results in 'false' value as default, which is the + // default value of Bool wrapper + if (tag != 0) { + os->stream_->ReadVarint64(&buffer64); + os->stream_->ReadTag(); + } + ow->RenderBool(field_name, buffer64 != 0); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderString(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + uint32 buffer32; + string str; // default value of empty for String wrapper + if (tag != 0) { + os->stream_->ReadVarint32(&buffer32); // string size. + os->stream_->ReadString(&str, buffer32); + os->stream_->ReadTag(); + } + ow->RenderString(field_name, str); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderBytes(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + uint32 buffer32; + string str; + if (tag != 0) { + os->stream_->ReadVarint32(&buffer32); + os->stream_->ReadString(&str, buffer32); + os->stream_->ReadTag(); + } + ow->RenderBytes(field_name, str); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderStruct(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + const google::protobuf::Field* field = NULL; + uint32 tag = os->stream_->ReadTag(); + ow->StartObject(field_name); + while (tag != 0) { + field = os->FindAndVerifyField(type, tag); + // google.protobuf.Struct has only one field that is a map. Hence we use + // RenderMap to render that field. + if (os->IsMap(*field)) { + ASSIGN_OR_RETURN(tag, os->RenderMap(field, field_name, tag, ow)); + } + } + ow->EndObject(); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderStructValue( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { + const google::protobuf::Field* field = NULL; + for (uint32 tag = os->stream_->ReadTag(); tag != 0; + tag = os->stream_->ReadTag()) { + field = os->FindAndVerifyField(type, tag); + if (field == NULL) { + WireFormat::SkipField(os->stream_, tag, NULL); + continue; + } + RETURN_IF_ERROR(os->RenderField(field, field_name, ow)); + } + return Status::OK; +} + +// TODO(skarvaje): Avoid code duplication of for loops and SkipField logic. +Status ProtoStreamObjectSource::RenderStructListValue( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + + // Render empty list when we find empty ListValue message. + if (tag == 0) { + ow->StartList(field_name); + ow->EndList(); + return Status::OK; + } + + while (tag != 0) { + const google::protobuf::Field* field = os->FindAndVerifyField(type, tag); + if (field == NULL) { + WireFormat::SkipField(os->stream_, tag, NULL); + tag = os->stream_->ReadTag(); + continue; + } + ASSIGN_OR_RETURN(tag, os->RenderList(field, field_name, tag, ow)); + } + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderAny(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + // An Any is of the form { string type_url = 1; bytes value = 2; } + uint32 tag; + string type_url; + string value; + + // First read out the type_url and value from the proto stream + for (tag = os->stream_->ReadTag(); tag != 0; tag = os->stream_->ReadTag()) { + const google::protobuf::Field* field = os->FindAndVerifyField(type, tag); + if (field == NULL) { + WireFormat::SkipField(os->stream_, tag, NULL); + continue; + } + // 'type_url' has field number of 1 and 'value' has field number 2 + // //google/protobuf/any.proto + if (field->number() == 1) { + // read type_url + uint32 type_url_size; + os->stream_->ReadVarint32(&type_url_size); + os->stream_->ReadString(&type_url, type_url_size); + } else if (field->number() == 2) { + // read value + uint32 value_size; + os->stream_->ReadVarint32(&value_size); + os->stream_->ReadString(&value, value_size); + } + } + + // If there is no value, we don't lookup the type, we just output it (if + // present). If both type and value are empty we output an empty object. + if (value.empty()) { + ow->StartObject(field_name); + if (!type_url.empty()) { + ow->RenderString("@type", type_url); + } + ow->EndObject(); + return util::Status::OK; + } + + // If there is a value but no type, we cannot render it, so report an error. + if (type_url.empty()) { + // TODO(sven): Add an external message once those are ready. + return util::Status(util::error::INTERNAL, + "Invalid Any, the type_url is missing."); + } + + util::StatusOr<const google::protobuf::Type*> resolved_type = + os->typeinfo_->ResolveTypeUrl(type_url); + + if (!resolved_type.ok()) { + // Convert into an internal error, since this means the backend gave us + // an invalid response (missing or invalid type information). + return util::Status(util::error::INTERNAL, + resolved_type.status().error_message()); + } + // nested_type cannot be null at this time. + const google::protobuf::Type* nested_type = resolved_type.ValueOrDie(); + + // We know the type so we can render it. Recursively parse the nested stream + // using a nested ProtoStreamObjectSource using our nested type information. + google::protobuf::io::ArrayInputStream zero_copy_stream(value.data(), value.size()); + google::protobuf::io::CodedInputStream in_stream(&zero_copy_stream); + ProtoStreamObjectSource nested_os(&in_stream, os->typeinfo_, *nested_type); + + // We manually call start and end object here so we can inject the @type. + ow->StartObject(field_name); + ow->RenderString("@type", type_url); + util::Status result = + nested_os.WriteMessage(nested_os.type_, "value", 0, false, ow); + ow->EndObject(); + return result; +} + +Status ProtoStreamObjectSource::RenderFieldMask( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { + string combined; + uint32 buffer32; + uint32 paths_field_tag = 0; + for (uint32 tag = os->stream_->ReadTag(); tag != 0; + tag = os->stream_->ReadTag()) { + if (paths_field_tag == 0) { + const google::protobuf::Field* field = os->FindAndVerifyField(type, tag); + if (field != NULL && field->number() == 1 && + field->name() == "paths") { + paths_field_tag = tag; + } + } + if (paths_field_tag != tag) { + return util::Status(util::error::INTERNAL, + "Invalid FieldMask, unexpected field."); + } + string str; + os->stream_->ReadVarint32(&buffer32); // string size. + os->stream_->ReadString(&str, buffer32); + if (!combined.empty()) { + combined.append(","); + } + combined.append(ConvertFieldMaskPath(str, &ToCamelCase)); + } + ow->RenderString(field_name, combined); + return Status::OK; +} + +hash_map<string, ProtoStreamObjectSource::TypeRenderer>* +ProtoStreamObjectSource::CreateRendererMap() { + hash_map<string, ProtoStreamObjectSource::TypeRenderer>* result = + new hash_map<string, ProtoStreamObjectSource::TypeRenderer>(); + (*result)["google.protobuf.Timestamp"] = + &ProtoStreamObjectSource::RenderTimestamp; + (*result)["google.protobuf.Duration"] = + &ProtoStreamObjectSource::RenderDuration; + (*result)["google.protobuf.DoubleValue"] = + &ProtoStreamObjectSource::RenderDouble; + (*result)["google.protobuf.FloatValue"] = + &ProtoStreamObjectSource::RenderFloat; + (*result)["google.protobuf.Int64Value"] = + &ProtoStreamObjectSource::RenderInt64; + (*result)["google.protobuf.UInt64Value"] = + &ProtoStreamObjectSource::RenderUInt64; + (*result)["google.protobuf.Int32Value"] = + &ProtoStreamObjectSource::RenderInt32; + (*result)["google.protobuf.UInt32Value"] = + &ProtoStreamObjectSource::RenderUInt32; + (*result)["google.protobuf.BoolValue"] = &ProtoStreamObjectSource::RenderBool; + (*result)["google.protobuf.StringValue"] = + &ProtoStreamObjectSource::RenderString; + (*result)["google.protobuf.BytesValue"] = + &ProtoStreamObjectSource::RenderBytes; + (*result)["google.protobuf.Any"] = &ProtoStreamObjectSource::RenderAny; + (*result)["google.protobuf.Struct"] = &ProtoStreamObjectSource::RenderStruct; + (*result)["google.protobuf.Value"] = + &ProtoStreamObjectSource::RenderStructValue; + (*result)["google.protobuf.ListValue"] = + &ProtoStreamObjectSource::RenderStructListValue; + (*result)["google.protobuf.FieldMask"] = + &ProtoStreamObjectSource::RenderFieldMask; + return result; +} + +// static +ProtoStreamObjectSource::TypeRenderer* +ProtoStreamObjectSource::FindTypeRenderer(const string& type_url) { + static hash_map<string, TypeRenderer>* renderers = CreateRendererMap(); + return FindOrNull(*renderers, type_url); +} + +Status ProtoStreamObjectSource::RenderField( + const google::protobuf::Field* field, StringPiece field_name, + ObjectWriter* ow) const { + switch (field->kind()) { + case google::protobuf::Field_Kind_TYPE_BOOL: { + uint64 buffer64; + stream_->ReadVarint64(&buffer64); + ow->RenderBool(field_name, buffer64 != 0); + break; + } + case google::protobuf::Field_Kind_TYPE_INT32: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); + ow->RenderInt32(field_name, bit_cast<int32>(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_INT64: { + uint64 buffer64; + stream_->ReadVarint64(&buffer64); + ow->RenderInt64(field_name, bit_cast<int64>(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_UINT32: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); + ow->RenderUint32(field_name, bit_cast<uint32>(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_UINT64: { + uint64 buffer64; + stream_->ReadVarint64(&buffer64); + ow->RenderUint64(field_name, bit_cast<uint64>(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_SINT32: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); + ow->RenderInt32(field_name, WireFormatLite::ZigZagDecode32(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_SINT64: { + uint64 buffer64; + stream_->ReadVarint64(&buffer64); + ow->RenderInt64(field_name, WireFormatLite::ZigZagDecode64(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_SFIXED32: { + uint32 buffer32; + stream_->ReadLittleEndian32(&buffer32); + ow->RenderInt32(field_name, bit_cast<int32>(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_SFIXED64: { + uint64 buffer64; + stream_->ReadLittleEndian64(&buffer64); + ow->RenderInt64(field_name, bit_cast<int64>(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_FIXED32: { + uint32 buffer32; + stream_->ReadLittleEndian32(&buffer32); + ow->RenderUint32(field_name, bit_cast<uint32>(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_FIXED64: { + uint64 buffer64; + stream_->ReadLittleEndian64(&buffer64); + ow->RenderUint64(field_name, bit_cast<uint64>(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_FLOAT: { + uint32 buffer32; + stream_->ReadLittleEndian32(&buffer32); + ow->RenderFloat(field_name, bit_cast<float>(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_DOUBLE: { + uint64 buffer64; + stream_->ReadLittleEndian64(&buffer64); + ow->RenderDouble(field_name, bit_cast<double>(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_ENUM: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); + + // If the field represents an explicit NULL value, render null. + if (field->type_url() == kStructNullValueTypeUrl) { + ow->RenderNull(field_name); + break; + } + + // Get the nested enum type for this field. + // TODO(skarvaje): Avoid string manipulation. Find ways to speed this + // up. + const google::protobuf::Enum* en = typeinfo_->GetEnum(field->type_url()); + // Lookup the name of the enum, and render that. Skips unknown enums. + if (en != NULL) { + const google::protobuf::EnumValue* enum_value = + FindEnumValueByNumber(*en, buffer32); + if (enum_value != NULL) { + ow->RenderString(field_name, enum_value->name()); + } + } else { + GOOGLE_LOG(INFO) << "Unkown enum skipped: " << field->type_url(); + } + break; + } + case google::protobuf::Field_Kind_TYPE_STRING: { + uint32 buffer32; + string str; + stream_->ReadVarint32(&buffer32); // string size. + stream_->ReadString(&str, buffer32); + ow->RenderString(field_name, str); + break; + } + case google::protobuf::Field_Kind_TYPE_BYTES: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); // bytes size. + string value; + stream_->ReadString(&value, buffer32); + ow->RenderBytes(field_name, value); + break; + } + case google::protobuf::Field_Kind_TYPE_MESSAGE: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); // message length + int old_limit = stream_->PushLimit(buffer32); + // Get the nested message type for this field. + const google::protobuf::Type* type = + typeinfo_->GetType(field->type_url()); + if (type == NULL) { + return Status(util::error::INTERNAL, + StrCat("Invalid configuration. Could not find the type: ", + field->type_url())); + } + RETURN_IF_ERROR(WriteMessage(*type, field_name, 0, true, ow)); + if (!stream_->ConsumedEntireMessage()) { + return Status(util::error::INVALID_ARGUMENT, + "Nested protocol message not parsed in its entirety."); + } + stream_->PopLimit(old_limit); + break; + } + default: + break; + } + return Status::OK; +} + +// TODO(skarvaje): Fix this to avoid code duplication. +const string ProtoStreamObjectSource::ReadFieldValueAsString( + const google::protobuf::Field& field) const { + string result; + switch (field.kind()) { + case google::protobuf::Field_Kind_TYPE_BOOL: { + uint64 buffer64; + stream_->ReadVarint64(&buffer64); + result = buffer64 != 0 ? "true" : "false"; + break; + } + case google::protobuf::Field_Kind_TYPE_INT32: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); + result = SimpleItoa(bit_cast<int32>(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_INT64: { + uint64 buffer64; + stream_->ReadVarint64(&buffer64); + result = SimpleItoa(bit_cast<int64>(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_UINT32: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); + result = SimpleItoa(bit_cast<uint32>(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_UINT64: { + uint64 buffer64; + stream_->ReadVarint64(&buffer64); + result = SimpleItoa(bit_cast<uint64>(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_SINT32: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); + result = SimpleItoa(WireFormatLite::ZigZagDecode32(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_SINT64: { + uint64 buffer64; + stream_->ReadVarint64(&buffer64); + result = SimpleItoa(WireFormatLite::ZigZagDecode64(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_SFIXED32: { + uint32 buffer32; + stream_->ReadLittleEndian32(&buffer32); + result = SimpleItoa(bit_cast<int32>(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_SFIXED64: { + uint64 buffer64; + stream_->ReadLittleEndian64(&buffer64); + result = SimpleItoa(bit_cast<int64>(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_FIXED32: { + uint32 buffer32; + stream_->ReadLittleEndian32(&buffer32); + result = SimpleItoa(bit_cast<uint32>(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_FIXED64: { + uint64 buffer64; + stream_->ReadLittleEndian64(&buffer64); + result = SimpleItoa(bit_cast<uint64>(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_FLOAT: { + uint32 buffer32; + stream_->ReadLittleEndian32(&buffer32); + result = SimpleFtoa(bit_cast<float>(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_DOUBLE: { + uint64 buffer64; + stream_->ReadLittleEndian64(&buffer64); + result = SimpleDtoa(bit_cast<double>(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_ENUM: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); + // Get the nested enum type for this field. + // TODO(skarvaje): Avoid string manipulation. Find ways to speed this + // up. + const google::protobuf::Enum* en = typeinfo_->GetEnum(field.type_url()); + // Lookup the name of the enum, and render that. Skips unknown enums. + if (en != NULL) { + const google::protobuf::EnumValue* enum_value = + FindEnumValueByNumber(*en, buffer32); + if (enum_value != NULL) { + result = enum_value->name(); + } + } + break; + } + case google::protobuf::Field_Kind_TYPE_STRING: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); // string size. + stream_->ReadString(&result, buffer32); + break; + } + case google::protobuf::Field_Kind_TYPE_BYTES: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); // bytes size. + stream_->ReadString(&result, buffer32); + break; + } + default: + break; + } + return result; +} + +// Field is a map if it is a repeated message and it has an option "map_type". +// TODO(skarvaje): Consider pre-computing the IsMap() into Field directly. +bool ProtoStreamObjectSource::IsMap( + const google::protobuf::Field& field) const { + const google::protobuf::Type* field_type = + typeinfo_->GetType(field.type_url()); + + // TODO(xiaofeng): Unify option names. + return field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE && + (GetBoolOptionOrDefault(field_type->options(), + "google.protobuf.MessageOptions.map_entry", false) || + GetBoolOptionOrDefault(field_type->options(), "map_entry", false)); +} + +std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos( + const google::protobuf::Type& type) const { + uint64 seconds = 0; + uint32 nanos = 0; + uint32 tag = 0; + int64 signed_seconds = 0; + int64 signed_nanos = 0; + + for (tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) { + const google::protobuf::Field* field = FindAndVerifyField(type, tag); + if (field == NULL) { + WireFormat::SkipField(stream_, tag, NULL); + continue; + } + // 'seconds' has field number of 1 and 'nanos' has field number 2 + // //google/protobuf/timestamp.proto & duration.proto + if (field->number() == 1) { + // read seconds + stream_->ReadVarint64(&seconds); + signed_seconds = bit_cast<int64>(seconds); + } else if (field->number() == 2) { + // read nanos + stream_->ReadVarint32(&nanos); + signed_nanos = bit_cast<int32>(nanos); + } + } + return std::pair<int64, int32>(signed_seconds, signed_nanos); +} + +namespace { +// TODO(skarvaje): Speed this up by not doing a linear scan. +const google::protobuf::Field* FindFieldByNumber( + const google::protobuf::Type& type, int number) { + for (int i = 0; i < type.fields_size(); ++i) { + if (type.fields(i).number() == number) { + return &type.fields(i); + } + } + return NULL; +} + +// TODO(skarvaje): Replace FieldDescriptor by implementing IsTypePackable() +// using tech Field. +bool IsPackable(const google::protobuf::Field& field) { + return field.cardinality() == + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED && + google::protobuf::FieldDescriptor::IsTypePackable( + static_cast<google::protobuf::FieldDescriptor::Type>(field.kind())); +} + +// TODO(skarvaje): Speed this up by not doing a linear scan. +const google::protobuf::EnumValue* FindEnumValueByNumber( + const google::protobuf::Enum& tech_enum, int number) { + for (int i = 0; i < tech_enum.enumvalue_size(); ++i) { + const google::protobuf::EnumValue& ev = tech_enum.enumvalue(i); + if (ev.number() == number) { + return &ev; + } + } + return NULL; +} + +// TODO(skarvaje): Look into optimizing this by not doing computation on +// double. +const string FormatNanos(uint32 nanos) { + const char* format = + (nanos % 1000 != 0) ? "%.9f" : (nanos % 1000000 != 0) ? "%.6f" : "%.3f"; + string formatted = + StringPrintf(format, static_cast<double>(nanos) / kNanosPerSecond); + // remove the leading 0 before decimal. + return formatted.substr(1); +} +} // namespace + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h new file mode 100644 index 00000000..4a4e6bbf --- /dev/null +++ b/src/google/protobuf/util/internal/protostream_objectsource.h @@ -0,0 +1,245 @@ +// 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_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__ + +#include <functional> +#include <google/protobuf/stubs/hash.h> +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/type.pb.h> +#include <google/protobuf/util/internal/object_source.h> +#include <google/protobuf/util/internal/object_writer.h> +#include <google/protobuf/util/internal/type_info.h> +#include <google/protobuf/util/type_resolver.h> +#include <google/protobuf/stubs/stringpiece.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/statusor.h> + + + +namespace google { +namespace protobuf { +class Field; +class Type; +} // namespace protobuf + + +namespace protobuf { +namespace util { +namespace converter { + +class TypeInfo; + +// An ObjectSource that can parse a stream of bytes as a protocol buffer. +// This implementation uses a tech Type for tag lookup. +// +// Sample usage: (suppose input is: string proto) +// ArrayInputStream arr_stream(proto.data(), proto.size()); +// CodedInputStream in_stream(&arr_stream); +// ProtoStreamObjectSource os(&in_stream, /*ServiceTypeInfo*/ typeinfo, +// <your message google::protobuf::Type>); +// +// Status status = os.WriteTo(<some ObjectWriter>); +class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { + public: + ProtoStreamObjectSource(google::protobuf::io::CodedInputStream* stream, + TypeResolver* type_resolver, + const google::protobuf::Type& type); + + virtual ~ProtoStreamObjectSource(); + + virtual util::Status NamedWriteTo(StringPiece name, ObjectWriter* ow) const; + + protected: + // Writes a proto2 Message to the ObjectWriter. When the given end_tag is + // found this method will complete, allowing it to be used for parsing both + // nested messages (end with 0) and nested groups (end with group end tag). + // The include_start_and_end parameter allows this method to be called when + // already inside of an object, and skip calling StartObject and EndObject. + virtual util::Status WriteMessage(const google::protobuf::Type& descriptor, + StringPiece name, const uint32 end_tag, + bool include_start_and_end, + ObjectWriter* ow) const; + + private: + ProtoStreamObjectSource(google::protobuf::io::CodedInputStream* stream, + TypeInfo* typeinfo, + const google::protobuf::Type& type); + // Function that renders a well known type with a modified behavior. + typedef util::Status (*TypeRenderer)(const ProtoStreamObjectSource*, + const google::protobuf::Type&, + StringPiece, ObjectWriter*); + + // Looks up a field and verify its consistency with wire type in tag. + const google::protobuf::Field* FindAndVerifyField( + const google::protobuf::Type& type, uint32 tag) const; + + // TODO(skarvaje): Mark these methods as non-const as they modify internal + // state (stream_). + // + // Renders a repeating field (packed or unpacked). + // Returns the next tag after reading all sequential repeating elements. The + // caller should use this tag before reading more tags from the stream. + util::StatusOr<uint32> RenderList(const google::protobuf::Field* field, + StringPiece name, uint32 list_tag, + ObjectWriter* ow) const; + // Renders a NWP map. + // Returns the next tag after reading all map entries. The caller should use + // this tag before reading more tags from the stream. + util::StatusOr<uint32> RenderMap(const google::protobuf::Field* field, + StringPiece name, uint32 list_tag, + ObjectWriter* ow) const; + + // Renders an entry in a map, advancing stream pointers appropriately. + util::Status RenderMapEntry(const google::protobuf::Type* type, + ObjectWriter* ow) const; + + // Renders a packed repeating field. A packed field is stored as: + // {tag length item1 item2 item3} instead of the less efficient + // {tag item1 tag item2 tag item3}. + util::Status RenderPacked(const google::protobuf::Field* field, + ObjectWriter* ow) const; + + // Equivalent of RenderPacked, but for map entries. + util::Status RenderPackedMapEntry(const google::protobuf::Type* type, + ObjectWriter* ow) const; + + // Renders a google.protobuf.Timestamp value to ObjectWriter + static util::Status RenderTimestamp(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + // Renders a google.protobuf.Duration value to ObjectWriter + static util::Status RenderDuration(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + // Following RenderTYPE functions render well known types in + // google/protobuf/wrappers.proto corresponding to TYPE. + static util::Status RenderDouble(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderFloat(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderInt64(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderUInt64(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderInt32(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderUInt32(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderBool(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderString(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderBytes(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + // Renders a google.protobuf.Struct to ObjectWriter. + static util::Status RenderStruct(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + // Helper to render google.protobuf.Struct's Value fields to ObjectWriter. + static util::Status RenderStructValue(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + // Helper to render google.protobuf.Struct's ListValue fields to ObjectWriter. + static util::Status RenderStructListValue( + const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + // Render the "Any" type. + static util::Status RenderAny(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + // Render the "FieldMask" type. + static util::Status RenderFieldMask(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + static hash_map<string, TypeRenderer>* CreateRendererMap(); + static TypeRenderer* FindTypeRenderer(const string& type_url); + + // Renders a field value to the ObjectWriter. + util::Status RenderField(const google::protobuf::Field* field, + StringPiece field_name, ObjectWriter* ow) const; + + // Reads field value according to Field spec in 'field' and returns the read + // value as string. This only works for primitive datatypes (no message + // types). + const string ReadFieldValueAsString( + const google::protobuf::Field& field) const; + + // Utility function to detect proto maps. The 'field' MUST be repeated. + bool IsMap(const google::protobuf::Field& field) const; + + // Utility to read int64 and int32 values from a message type in stream_. + // Used for reading google.protobuf.Timestamp and Duration messages. + std::pair<int64, int32> ReadSecondsAndNanos( + const google::protobuf::Type& type) const; + + // Input stream to read from. Ownership rests with the caller. + google::protobuf::io::CodedInputStream* stream_; + + // Type information for all the types used in the descriptor. Used to find + // google::protobuf::Type of nested messages/enums. + TypeInfo* typeinfo_; + // Whether this class owns the typeinfo_ object. If true the typeinfo_ object + // should be deleted in the destructor. + bool own_typeinfo_; + + // google::protobuf::Type of the message source. + const google::protobuf::Type& type_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectSource); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__ diff --git a/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc new file mode 100644 index 00000000..4cc62410 --- /dev/null +++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc @@ -0,0 +1,824 @@ +// 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/util/internal/protostream_objectsource.h> + +#include <memory> +#ifndef _SHARED_PTR_H +#include <google/protobuf/stubs/shared_ptr.h> +#endif +#include <sstream> + +#include <google/protobuf/stubs/casts.h> +#include <google/protobuf/any.pb.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl_lite.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/util/internal/expecting_objectwriter.h> +#include <google/protobuf/util/internal/testdata/books.pb.h> +#include <google/protobuf/util/internal/testdata/field_mask.pb.h> +#include <google/protobuf/util/internal/type_info_test_helper.h> +#include <google/protobuf/util/internal/constants.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/util/internal/testdata/anys.pb.h> +#include <google/protobuf/util/internal/testdata/maps.pb.h> +#include <google/protobuf/util/internal/testdata/struct.pb.h> +#include <gtest/gtest.h> + + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +using google::protobuf::Descriptor; +using google::protobuf::DescriptorPool; +using google::protobuf::FileDescriptorProto; +using google::protobuf::Message; +using google::protobuf::io::ArrayInputStream; +using google::protobuf::io::CodedInputStream; +using util::Status; +using google::protobuf::testing::Author; +using google::protobuf::testing::BadAuthor; +using google::protobuf::testing::BadNestedBook; +using google::protobuf::testing::Book; +using google::protobuf::testing::Book_Label; +using google::protobuf::testing::NestedBook; +using google::protobuf::testing::PackedPrimitive; +using google::protobuf::testing::Primitive; +using google::protobuf::testing::more_author; +using google::protobuf::testing::maps::MapOut; +using google::protobuf::testing::anys::AnyOut; +using google::protobuf::testing::anys::AnyM; +using google::protobuf::testing::FieldMaskTest; +using google::protobuf::testing::NestedFieldMask; +using google::protobuf::testing::structs::StructType; +using ::testing::_; + + +namespace { +string GetTypeUrl(const Descriptor* descriptor) { + return string(kTypeServiceBaseUrl) + "/" + descriptor->full_name(); +} +} // namespace + +class ProtostreamObjectSourceTest + : public ::testing::TestWithParam<testing::TypeInfoSource> { + protected: + ProtostreamObjectSourceTest() : helper_(GetParam()), mock_(), ow_(&mock_) { + helper_.ResetTypeInfo(Book::descriptor()); + } + + virtual ~ProtostreamObjectSourceTest() {} + + void DoTest(const Message& msg, const Descriptor* descriptor) { + Status status = ExecuteTest(msg, descriptor); + EXPECT_EQ(Status::OK, status); + } + + Status ExecuteTest(const Message& msg, const Descriptor* descriptor) { + ostringstream oss; + msg.SerializePartialToOstream(&oss); + string proto = oss.str(); + ArrayInputStream arr_stream(proto.data(), proto.size()); + CodedInputStream in_stream(&arr_stream); + + google::protobuf::scoped_ptr<ProtoStreamObjectSource> os( + helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor))); + return os->WriteTo(&mock_); + } + + void PrepareExpectingObjectWriterForRepeatedPrimitive() { + ow_.StartObject("") + ->StartList("rep_fix32") + ->RenderUint32("", bit_cast<uint32>(3201)) + ->RenderUint32("", bit_cast<uint32>(0)) + ->RenderUint32("", bit_cast<uint32>(3202)) + ->EndList() + ->StartList("rep_u32") + ->RenderUint32("", bit_cast<uint32>(3203)) + ->RenderUint32("", bit_cast<uint32>(0)) + ->EndList() + ->StartList("rep_i32") + ->RenderInt32("", 0) + ->RenderInt32("", 3204) + ->RenderInt32("", 3205) + ->EndList() + ->StartList("rep_sf32") + ->RenderInt32("", 3206) + ->RenderInt32("", 0) + ->EndList() + ->StartList("rep_s32") + ->RenderInt32("", 0) + ->RenderInt32("", 3207) + ->RenderInt32("", 3208) + ->EndList() + ->StartList("rep_fix64") + ->RenderUint64("", bit_cast<uint64>(6401LL)) + ->RenderUint64("", bit_cast<uint64>(0LL)) + ->EndList() + ->StartList("rep_u64") + ->RenderUint64("", bit_cast<uint64>(0LL)) + ->RenderUint64("", bit_cast<uint64>(6402LL)) + ->RenderUint64("", bit_cast<uint64>(6403LL)) + ->EndList() + ->StartList("rep_i64") + ->RenderInt64("", 6404L) + ->RenderInt64("", 0L) + ->EndList() + ->StartList("rep_sf64") + ->RenderInt64("", 0L) + ->RenderInt64("", 6405L) + ->RenderInt64("", 6406L) + ->EndList() + ->StartList("rep_s64") + ->RenderInt64("", 6407L) + ->RenderInt64("", 0L) + ->EndList() + ->StartList("rep_float") + ->RenderFloat("", 0.0f) + ->RenderFloat("", 32.1f) + ->RenderFloat("", 32.2f) + ->EndList() + ->StartList("rep_double") + ->RenderDouble("", 64.1L) + ->RenderDouble("", 0.0L) + ->EndList() + ->StartList("rep_bool") + ->RenderBool("", true) + ->RenderBool("", false) + ->EndList() + ->EndObject(); + } + + Primitive PrepareRepeatedPrimitive() { + Primitive primitive; + primitive.add_rep_fix32(3201); + primitive.add_rep_fix32(0); + primitive.add_rep_fix32(3202); + primitive.add_rep_u32(3203); + primitive.add_rep_u32(0); + primitive.add_rep_i32(0); + primitive.add_rep_i32(3204); + primitive.add_rep_i32(3205); + primitive.add_rep_sf32(3206); + primitive.add_rep_sf32(0); + primitive.add_rep_s32(0); + primitive.add_rep_s32(3207); + primitive.add_rep_s32(3208); + primitive.add_rep_fix64(6401L); + primitive.add_rep_fix64(0L); + primitive.add_rep_u64(0L); + primitive.add_rep_u64(6402L); + primitive.add_rep_u64(6403L); + primitive.add_rep_i64(6404L); + primitive.add_rep_i64(0L); + primitive.add_rep_sf64(0L); + primitive.add_rep_sf64(6405L); + primitive.add_rep_sf64(6406L); + primitive.add_rep_s64(6407L); + primitive.add_rep_s64(0L); + primitive.add_rep_float(0.0f); + primitive.add_rep_float(32.1f); + primitive.add_rep_float(32.2f); + primitive.add_rep_double(64.1L); + primitive.add_rep_double(0.0); + primitive.add_rep_bool(true); + primitive.add_rep_bool(false); + + PrepareExpectingObjectWriterForRepeatedPrimitive(); + return primitive; + } + + PackedPrimitive PreparePackedPrimitive() { + PackedPrimitive primitive; + primitive.add_rep_fix32(3201); + primitive.add_rep_fix32(0); + primitive.add_rep_fix32(3202); + primitive.add_rep_u32(3203); + primitive.add_rep_u32(0); + primitive.add_rep_i32(0); + primitive.add_rep_i32(3204); + primitive.add_rep_i32(3205); + primitive.add_rep_sf32(3206); + primitive.add_rep_sf32(0); + primitive.add_rep_s32(0); + primitive.add_rep_s32(3207); + primitive.add_rep_s32(3208); + primitive.add_rep_fix64(6401L); + primitive.add_rep_fix64(0L); + primitive.add_rep_u64(0L); + primitive.add_rep_u64(6402L); + primitive.add_rep_u64(6403L); + primitive.add_rep_i64(6404L); + primitive.add_rep_i64(0L); + primitive.add_rep_sf64(0L); + primitive.add_rep_sf64(6405L); + primitive.add_rep_sf64(6406L); + primitive.add_rep_s64(6407L); + primitive.add_rep_s64(0L); + primitive.add_rep_float(0.0f); + primitive.add_rep_float(32.1f); + primitive.add_rep_float(32.2f); + primitive.add_rep_double(64.1L); + primitive.add_rep_double(0.0); + primitive.add_rep_bool(true); + primitive.add_rep_bool(false); + + PrepareExpectingObjectWriterForRepeatedPrimitive(); + return primitive; + } + + testing::TypeInfoTestHelper helper_; + + ::testing::NiceMock<MockObjectWriter> mock_; + ExpectingObjectWriter ow_; +}; + +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + ProtostreamObjectSourceTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + +TEST_P(ProtostreamObjectSourceTest, EmptyMessage) { + Book empty; + ow_.StartObject("")->EndObject(); + DoTest(empty, Book::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, Primitives) { + Primitive primitive; + primitive.set_fix32(3201); + primitive.set_u32(3202); + primitive.set_i32(3203); + primitive.set_sf32(3204); + primitive.set_s32(3205); + primitive.set_fix64(6401L); + primitive.set_u64(6402L); + primitive.set_i64(6403L); + primitive.set_sf64(6404L); + primitive.set_s64(6405L); + primitive.set_str("String Value"); + primitive.set_bytes("Some Bytes"); + primitive.set_float_(32.1f); + primitive.set_double_(64.1L); + primitive.set_bool_(true); + + ow_.StartObject("") + ->RenderUint32("fix32", bit_cast<uint32>(3201)) + ->RenderUint32("u32", bit_cast<uint32>(3202)) + ->RenderInt32("i32", 3203) + ->RenderInt32("sf32", 3204) + ->RenderInt32("s32", 3205) + ->RenderUint64("fix64", bit_cast<uint64>(6401LL)) + ->RenderUint64("u64", bit_cast<uint64>(6402LL)) + ->RenderInt64("i64", 6403L) + ->RenderInt64("sf64", 6404L) + ->RenderInt64("s64", 6405L) + ->RenderString("str", "String Value") + ->RenderBytes("bytes", "Some Bytes") + ->RenderFloat("float", 32.1f) + ->RenderDouble("double", 64.1L) + ->RenderBool("bool", true) + ->EndObject(); + DoTest(primitive, Primitive::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, RepeatingPrimitives) { + Primitive primitive = PrepareRepeatedPrimitive(); + primitive.add_rep_str("String One"); + primitive.add_rep_str("String Two"); + primitive.add_rep_bytes("Some Bytes"); + + ow_.StartList("rep_str") + ->RenderString("", "String One") + ->RenderString("", "String Two") + ->EndList() + ->StartList("rep_bytes") + ->RenderBytes("", "Some Bytes") + ->EndList(); + DoTest(primitive, Primitive::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, NestedMessage) { + Author* author = new Author(); + author->set_id(101L); + author->set_name("Tolstoy"); + Book book; + book.set_title("My Book"); + book.set_allocated_author(author); + + ow_.StartObject("") + ->RenderString("title", "My Book") + ->StartObject("author") + ->RenderUint64("id", bit_cast<uint64>(101LL)) + ->RenderString("name", "Tolstoy") + ->EndObject() + ->EndObject(); + DoTest(book, Book::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, RepeatingField) { + Author author; + author.set_alive(false); + author.set_name("john"); + author.add_pseudonym("phil"); + author.add_pseudonym("bob"); + + ow_.StartObject("") + ->RenderBool("alive", false) + ->RenderString("name", "john") + ->StartList("pseudonym") + ->RenderString("", "phil") + ->RenderString("", "bob") + ->EndList() + ->EndObject(); + DoTest(author, Author::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, PackedRepeatingFields) { + DoTest(PreparePackedPrimitive(), PackedPrimitive::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, NonPackedPackableFieldsActuallyPacked) { + // Protostream is packed, but parse with non-packed Primitive. + DoTest(PreparePackedPrimitive(), Primitive::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, PackedPackableFieldNotActuallyPacked) { + // Protostream is not packed, but parse with PackedPrimitive. + DoTest(PrepareRepeatedPrimitive(), PackedPrimitive::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, BadAuthor) { + Author author; + author.set_alive(false); + author.set_name("john"); + author.set_id(1234L); + author.add_pseudonym("phil"); + author.add_pseudonym("bob"); + + ow_.StartObject("") + ->StartList("alive") + ->RenderBool("", false) + ->EndList() + ->StartList("name") + ->RenderUint64("", static_cast<uint64>('j')) + ->RenderUint64("", static_cast<uint64>('o')) + ->RenderUint64("", static_cast<uint64>('h')) + ->RenderUint64("", static_cast<uint64>('n')) + ->EndList() + ->RenderString("pseudonym", "phil") + ->RenderString("pseudonym", "bob") + ->EndObject(); + // Protostream created with Author, but parsed with BadAuthor. + DoTest(author, BadAuthor::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, NestedBookToBadNestedBook) { + Book* book = new Book(); + book->set_length(250); + book->set_published(2014L); + NestedBook nested; + nested.set_allocated_book(book); + + ow_.StartObject("") + ->StartList("book") + ->RenderUint32("", 24) // tag for field length (3 << 3) + ->RenderUint32("", 250) + ->RenderUint32("", 32) // tag for field published (4 << 3) + ->RenderUint32("", 2014) + ->EndList() + ->EndObject(); + // Protostream created with NestedBook, but parsed with BadNestedBook. + DoTest(nested, BadNestedBook::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, BadNestedBookToNestedBook) { + BadNestedBook nested; + nested.add_book(1); + nested.add_book(2); + nested.add_book(3); + nested.add_book(4); + nested.add_book(5); + nested.add_book(6); + nested.add_book(7); + + ow_.StartObject("")->StartObject("book")->EndObject()->EndObject(); + // Protostream created with BadNestedBook, but parsed with NestedBook. + DoTest(nested, NestedBook::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, + LongRepeatedListDoesNotBreakIntoMultipleJsonLists) { + Book book; + + int repeat = 10000; + for (int i = 0; i < repeat; ++i) { + Book_Label* label = book.add_labels(); + label->set_key(StrCat("i", i)); + label->set_value(StrCat("v", i)); + } + + // Make sure StartList and EndList are called exactly once (see b/18227499 for + // problems when this doesn't happen) + EXPECT_CALL(mock_, StartList(_)).Times(1); + EXPECT_CALL(mock_, EndList()).Times(1); + + DoTest(book, Book::descriptor()); +} + +class ProtostreamObjectSourceMapsTest : public ProtostreamObjectSourceTest { + protected: + ProtostreamObjectSourceMapsTest() { + helper_.ResetTypeInfo(MapOut::descriptor()); + } +}; + +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + ProtostreamObjectSourceMapsTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + +// Tests JSON map. +// +// This is the example expected output. +// { +// "map1": { +// "key1": { +// "foo": "foovalue" +// }, +// "key2": { +// "foo": "barvalue" +// } +// }, +// "map2": { +// "nestedself": { +// "map1": { +// "nested_key1": { +// "foo": "nested_foo" +// } +// }, +// "bar": "nested_bar_string" +// } +// }, +// "map3": { +// "111": "one one one" +// }, +// "bar": "top bar" +// } +TEST_P(ProtostreamObjectSourceMapsTest, MapsTest) { + MapOut out; + (*out.mutable_map1())["key1"].set_foo("foovalue"); + (*out.mutable_map1())["key2"].set_foo("barvalue"); + + MapOut* nested_value = &(*out.mutable_map2())["nestedself"]; + (*nested_value->mutable_map1())["nested_key1"].set_foo("nested_foo"); + nested_value->set_bar("nested_bar_string"); + + (*out.mutable_map3())[111] = "one one one"; + + out.set_bar("top bar"); + + ow_.StartObject("") + ->StartObject("map1") + ->StartObject("key1") + ->RenderString("foo", "foovalue") + ->EndObject() + ->StartObject("key2") + ->RenderString("foo", "barvalue") + ->EndObject() + ->StartObject("map2") + ->StartObject("nestedself") + ->StartObject("map1") + ->StartObject("nested_key1") + ->RenderString("foo", "nested_foo") + ->EndObject() + ->EndObject() + ->RenderString("bar", "nested_bar_string") + ->EndObject() + ->EndObject() + ->StartObject("map3") + ->RenderString("111", "one one one") + ->EndObject() + ->EndObject() + ->RenderString("bar", "top bar") + ->EndObject(); + + DoTest(out, MapOut::descriptor()); +} + +class ProtostreamObjectSourceAnysTest : public ProtostreamObjectSourceTest { + protected: + ProtostreamObjectSourceAnysTest() { + helper_.ResetTypeInfo(AnyOut::descriptor(), + google::protobuf::Any::descriptor()); + } +}; + +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + ProtostreamObjectSourceAnysTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + +// Tests JSON any support. +// +// This is the example expected output. +// { +// "any": { +// "@type": "type.googleapis.com/google.protobuf.testing.anys.AnyM" +// "foo": "foovalue" +// } +// } +TEST_P(ProtostreamObjectSourceAnysTest, BasicAny) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + + AnyM m; + m.set_foo("foovalue"); + any->PackFrom(m); + + ow_.StartObject("") + ->StartObject("any") + ->RenderString("@type", + "type.googleapis.com/google.protobuf.testing.anys.AnyM") + ->RenderString("foo", "foovalue") + ->EndObject() + ->EndObject(); + + DoTest(out, AnyOut::descriptor()); +} + +TEST_P(ProtostreamObjectSourceAnysTest, RecursiveAny) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + any->set_type_url("type.googleapis.com/google.protobuf.Any"); + + ::google::protobuf::Any nested_any; + nested_any.set_type_url( + "type.googleapis.com/google.protobuf.testing.anys.AnyM"); + + AnyM m; + m.set_foo("foovalue"); + nested_any.set_value(m.SerializeAsString()); + + any->set_value(nested_any.SerializeAsString()); + + ow_.StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Any") + ->StartObject("value") + ->RenderString("@type", + "type.googleapis.com/google.protobuf.testing.anys.AnyM") + ->RenderString("foo", "foovalue") + ->EndObject() + ->EndObject() + ->EndObject(); + + DoTest(out, AnyOut::descriptor()); +} + +TEST_P(ProtostreamObjectSourceAnysTest, DoubleRecursiveAny) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + any->set_type_url("type.googleapis.com/google.protobuf.Any"); + + ::google::protobuf::Any nested_any; + nested_any.set_type_url("type.googleapis.com/google.protobuf.Any"); + + ::google::protobuf::Any second_nested_any; + second_nested_any.set_type_url( + "type.googleapis.com/google.protobuf.testing.anys.AnyM"); + + AnyM m; + m.set_foo("foovalue"); + second_nested_any.set_value(m.SerializeAsString()); + nested_any.set_value(second_nested_any.SerializeAsString()); + any->set_value(nested_any.SerializeAsString()); + + ow_.StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Any") + ->StartObject("value") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Any") + ->StartObject("value") + ->RenderString("@type", + "type.googleapis.com/google.protobuf.testing.anys.AnyM") + ->RenderString("foo", "foovalue") + ->EndObject() + ->EndObject() + ->EndObject() + ->EndObject(); + + DoTest(out, AnyOut::descriptor()); +} + +TEST_P(ProtostreamObjectSourceAnysTest, EmptyAnyOutputsEmptyObject) { + AnyOut out; + out.mutable_any(); + + ow_.StartObject("")->StartObject("any")->EndObject()->EndObject(); + + DoTest(out, AnyOut::descriptor()); +} + +TEST_P(ProtostreamObjectSourceAnysTest, EmptyWithTypeAndNoValueOutputsType) { + AnyOut out; + out.mutable_any()->set_type_url("foo.googleapis.com/my.Type"); + + ow_.StartObject("") + ->StartObject("any") + ->RenderString("@type", "foo.googleapis.com/my.Type") + ->EndObject() + ->EndObject(); + + DoTest(out, AnyOut::descriptor()); +} + +TEST_P(ProtostreamObjectSourceAnysTest, MissingTypeUrlError) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + + AnyM m; + m.set_foo("foovalue"); + any->set_value(m.SerializeAsString()); + + // We start the "AnyOut" part and then fail when we hit the Any object. + ow_.StartObject(""); + + Status status = ExecuteTest(out, AnyOut::descriptor()); + EXPECT_EQ(util::error::INTERNAL, status.error_code()); +} + +TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeServiceError) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + any->set_type_url("foo.googleapis.com/my.own.Type"); + + AnyM m; + m.set_foo("foovalue"); + any->set_value(m.SerializeAsString()); + + // We start the "AnyOut" part and then fail when we hit the Any object. + ow_.StartObject(""); + + Status status = ExecuteTest(out, AnyOut::descriptor()); + EXPECT_EQ(util::error::INTERNAL, status.error_code()); +} + +TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeError) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + any->set_type_url("type.googleapis.com/unknown.Type"); + + AnyM m; + m.set_foo("foovalue"); + any->set_value(m.SerializeAsString()); + + // We start the "AnyOut" part and then fail when we hit the Any object. + ow_.StartObject(""); + + Status status = ExecuteTest(out, AnyOut::descriptor()); + EXPECT_EQ(util::error::INTERNAL, status.error_code()); +} + +class ProtostreamObjectSourceStructTest : public ProtostreamObjectSourceTest { + protected: + ProtostreamObjectSourceStructTest() { + helper_.ResetTypeInfo(StructType::descriptor(), + google::protobuf::Struct::descriptor()); + } +}; + +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + ProtostreamObjectSourceStructTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + +// Tests struct +// +// "object": { +// "k1": 123, +// "k2": true +// } +TEST_P(ProtostreamObjectSourceStructTest, StructRenderSuccess) { + StructType out; + google::protobuf::Struct* s = out.mutable_object(); + s->mutable_fields()->operator[]("k1").set_number_value(123); + s->mutable_fields()->operator[]("k2").set_bool_value(true); + + ow_.StartObject("") + ->StartObject("object") + ->RenderDouble("k1", 123) + ->RenderBool("k2", true) + ->EndObject() + ->EndObject(); + + DoTest(out, StructType::descriptor()); +} + +TEST_P(ProtostreamObjectSourceStructTest, MissingValueSkipsField) { + StructType out; + google::protobuf::Struct* s = out.mutable_object(); + s->mutable_fields()->operator[]("k1"); + + ow_.StartObject("")->StartObject("object")->EndObject()->EndObject(); + + DoTest(out, StructType::descriptor()); +} + +class ProtostreamObjectSourceFieldMaskTest + : public ProtostreamObjectSourceTest { + protected: + ProtostreamObjectSourceFieldMaskTest() { + helper_.ResetTypeInfo(FieldMaskTest::descriptor(), + google::protobuf::FieldMask::descriptor()); + } +}; + +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + ProtostreamObjectSourceFieldMaskTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + +TEST_P(ProtostreamObjectSourceFieldMaskTest, FieldMaskRenderSuccess) { + FieldMaskTest out; + out.set_id("1"); + out.mutable_single_mask()->add_paths("path1"); + out.mutable_single_mask()->add_paths("snake_case_path2"); + ::google::protobuf::FieldMask* mask = out.add_repeated_mask(); + mask->add_paths("path3"); + mask = out.add_repeated_mask(); + mask->add_paths("snake_case_path4"); + mask->add_paths("path5"); + NestedFieldMask* nested = out.add_nested_mask(); + nested->set_data("data"); + nested->mutable_single_mask()->add_paths("nested.path1"); + nested->mutable_single_mask()->add_paths("nested_field.snake_case_path2"); + mask = nested->add_repeated_mask(); + mask->add_paths("nested_field.path3"); + mask->add_paths("nested.snake_case_path4"); + mask = nested->add_repeated_mask(); + mask->add_paths("nested.path5"); + mask = nested->add_repeated_mask(); + mask->add_paths( + "snake_case.map_field[\"map_key_should_be_ignored\"].nested_snake_case." + "map_field[\"map_key_sho\\\"uld_be_ignored\"]"); + + ow_.StartObject("") + ->RenderString("id", "1") + ->RenderString("single_mask", "path1,snakeCasePath2") + ->StartList("repeated_mask") + ->RenderString("", "path3") + ->RenderString("", "snakeCasePath4,path5") + ->EndList() + ->StartList("nested_mask") + ->StartObject("") + ->RenderString("data", "data") + ->RenderString("single_mask", "nested.path1,nestedField.snakeCasePath2") + ->StartList("repeated_mask") + ->RenderString("", "nestedField.path3,nested.snakeCasePath4") + ->RenderString("", "nested.path5") + ->RenderString("", + "snakeCase.mapField[\"map_key_should_be_ignored\"]." + "nestedSnakeCase.mapField[\"map_key_sho\\\"uld_be_" + "ignored\"]") + ->EndList() + ->EndObject() + ->EndList() + ->EndObject(); + + DoTest(out, FieldMaskTest::descriptor()); +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc new file mode 100644 index 00000000..f9ddbf32 --- /dev/null +++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc @@ -0,0 +1,1557 @@ +// 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/util/internal/protostream_objectwriter.h> + +#include <functional> +#include <stack> + +#include <google/protobuf/stubs/time.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/util/internal/field_mask_utility.h> +#include <google/protobuf/util/internal/object_location_tracker.h> +#include <google/protobuf/util/internal/constants.h> +#include <google/protobuf/util/internal/utility.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/map_util.h> +#include <google/protobuf/stubs/statusor.h> + + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +using google::protobuf::internal::WireFormatLite; +using google::protobuf::io::CodedOutputStream; +using util::error::INVALID_ARGUMENT; +using util::Status; +using util::StatusOr; + + +ProtoStreamObjectWriter::ProtoStreamObjectWriter( + TypeResolver* type_resolver, const google::protobuf::Type& type, + strings::ByteSink* output, ErrorListener* listener) + : master_type_(type), + typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), + own_typeinfo_(true), + done_(false), + element_(NULL), + size_insert_(), + output_(output), + buffer_(), + adapter_(&buffer_), + stream_(new CodedOutputStream(&adapter_)), + listener_(listener), + invalid_depth_(0), + tracker_(new ObjectLocationTracker()) {} + +ProtoStreamObjectWriter::ProtoStreamObjectWriter( + TypeInfo* typeinfo, const google::protobuf::Type& type, + strings::ByteSink* output, ErrorListener* listener) + : master_type_(type), + typeinfo_(typeinfo), + own_typeinfo_(false), + done_(false), + element_(NULL), + size_insert_(), + output_(output), + buffer_(), + adapter_(&buffer_), + stream_(new CodedOutputStream(&adapter_)), + listener_(listener), + invalid_depth_(0), + tracker_(new ObjectLocationTracker()) {} + +ProtoStreamObjectWriter::~ProtoStreamObjectWriter() { + // Cleanup explicitly in order to avoid destructor stack overflow when input + // is deeply nested. + while (element_ != NULL) { + element_.reset(element_->pop()); + } + if (own_typeinfo_) { + delete typeinfo_; + } +} + +namespace { + +// Writes an INT32 field, including tag to the stream. +inline Status WriteInt32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr<int32> i32 = data.ToInt32(); + if (i32.ok()) { + WireFormatLite::WriteInt32(field_number, i32.ValueOrDie(), stream); + } + return i32.status(); +} + +// writes an SFIXED32 field, including tag, to the stream. +inline Status WriteSFixed32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr<int32> i32 = data.ToInt32(); + if (i32.ok()) { + WireFormatLite::WriteSFixed32(field_number, i32.ValueOrDie(), stream); + } + return i32.status(); +} + +// Writes an SINT32 field, including tag, to the stream. +inline Status WriteSInt32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr<int32> i32 = data.ToInt32(); + if (i32.ok()) { + WireFormatLite::WriteSInt32(field_number, i32.ValueOrDie(), stream); + } + return i32.status(); +} + +// Writes a FIXED32 field, including tag, to the stream. +inline Status WriteFixed32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr<uint32> u32 = data.ToUint32(); + if (u32.ok()) { + WireFormatLite::WriteFixed32(field_number, u32.ValueOrDie(), stream); + } + return u32.status(); +} + +// Writes a UINT32 field, including tag, to the stream. +inline Status WriteUInt32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr<uint32> u32 = data.ToUint32(); + if (u32.ok()) { + WireFormatLite::WriteUInt32(field_number, u32.ValueOrDie(), stream); + } + return u32.status(); +} + +// Writes an INT64 field, including tag, to the stream. +inline Status WriteInt64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr<int64> i64 = data.ToInt64(); + if (i64.ok()) { + WireFormatLite::WriteInt64(field_number, i64.ValueOrDie(), stream); + } + return i64.status(); +} + +// Writes an SFIXED64 field, including tag, to the stream. +inline Status WriteSFixed64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr<int64> i64 = data.ToInt64(); + if (i64.ok()) { + WireFormatLite::WriteSFixed64(field_number, i64.ValueOrDie(), stream); + } + return i64.status(); +} + +// Writes an SINT64 field, including tag, to the stream. +inline Status WriteSInt64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr<int64> i64 = data.ToInt64(); + if (i64.ok()) { + WireFormatLite::WriteSInt64(field_number, i64.ValueOrDie(), stream); + } + return i64.status(); +} + +// Writes a FIXED64 field, including tag, to the stream. +inline Status WriteFixed64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr<uint64> u64 = data.ToUint64(); + if (u64.ok()) { + WireFormatLite::WriteFixed64(field_number, u64.ValueOrDie(), stream); + } + return u64.status(); +} + +// Writes a UINT64 field, including tag, to the stream. +inline Status WriteUInt64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr<uint64> u64 = data.ToUint64(); + if (u64.ok()) { + WireFormatLite::WriteUInt64(field_number, u64.ValueOrDie(), stream); + } + return u64.status(); +} + +// Writes a DOUBLE field, including tag, to the stream. +inline Status WriteDouble(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr<double> d = data.ToDouble(); + if (d.ok()) { + WireFormatLite::WriteDouble(field_number, d.ValueOrDie(), stream); + } + return d.status(); +} + +// Writes a FLOAT field, including tag, to the stream. +inline Status WriteFloat(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr<float> f = data.ToFloat(); + if (f.ok()) { + WireFormatLite::WriteFloat(field_number, f.ValueOrDie(), stream); + } + return f.status(); +} + +// Writes a BOOL field, including tag, to the stream. +inline Status WriteBool(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr<bool> b = data.ToBool(); + if (b.ok()) { + WireFormatLite::WriteBool(field_number, b.ValueOrDie(), stream); + } + return b.status(); +} + +// Writes a BYTES field, including tag, to the stream. +inline Status WriteBytes(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr<string> c = data.ToBytes(); + if (c.ok()) { + WireFormatLite::WriteBytes(field_number, c.ValueOrDie(), stream); + } + return c.status(); +} + +// Writes a STRING field, including tag, to the stream. +inline Status WriteString(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr<string> s = data.ToString(); + if (s.ok()) { + WireFormatLite::WriteString(field_number, s.ValueOrDie(), stream); + } + return s.status(); +} + +// Writes an ENUM field, including tag, to the stream. +inline Status WriteEnum(int field_number, const DataPiece& data, + const google::protobuf::Enum* enum_type, + CodedOutputStream* stream) { + StatusOr<int> e = data.ToEnum(enum_type); + if (e.ok()) { + WireFormatLite::WriteEnum(field_number, e.ValueOrDie(), stream); + } + return e.status(); +} + +// Given a google::protobuf::Type, returns the set of all required fields. +std::set<const google::protobuf::Field*> GetRequiredFields( + const google::protobuf::Type& type) { + std::set<const google::protobuf::Field*> required; + for (int i = 0; i < type.fields_size(); i++) { + const google::protobuf::Field& field = type.fields(i); + if (field.cardinality() == + google::protobuf::Field_Cardinality_CARDINALITY_REQUIRED) { + required.insert(&field); + } + } + return required; +} + +// Utility method to split a string representation of Timestamp or Duration and +// return the parts. +void SplitSecondsAndNanos(StringPiece input, StringPiece* seconds, + StringPiece* nanos) { + size_t idx = input.rfind('.'); + if (idx != string::npos) { + *seconds = input.substr(0, idx); + *nanos = input.substr(idx + 1); + } else { + *seconds = input; + *nanos = StringPiece(); + } +} + +} // namespace + +ProtoStreamObjectWriter::AnyWriter::AnyWriter(ProtoStreamObjectWriter* parent) + : parent_(parent), + ow_(), + invalid_(false), + data_(), + output_(&data_), + depth_(0), + has_injected_value_message_(false) {} + +ProtoStreamObjectWriter::AnyWriter::~AnyWriter() {} + +void ProtoStreamObjectWriter::AnyWriter::StartObject(StringPiece name) { + ++depth_; + // If an object writer is absent, that means we have not called StartAny() + // before reaching here. This is an invalid state. StartAny() gets called + // whenever we see an "@type" being rendered (see AnyWriter::RenderDataPiece). + if (ow_ == NULL) { + // Make sure we are not already in an invalid state. This avoids making + // multiple unnecessary InvalidValue calls. + if (!invalid_) { + parent_->InvalidValue("Any", + StrCat("Missing or invalid @type for any field in ", + parent_->master_type_.name())); + invalid_ = true; + } + } else if (!has_injected_value_message_ || depth_ != 1 || name != "value") { + // We don't propagate to ow_ StartObject("value") calls for nested Anys or + // Struct at depth 1 as they are nested one level deep with an injected + // "value" field. + ow_->StartObject(name); + } +} + +bool ProtoStreamObjectWriter::AnyWriter::EndObject() { + --depth_; + // As long as depth_ >= 0, we know we haven't reached the end of Any. + // Propagate these EndObject() calls to the contained ow_. If we are in a + // nested Any or Struct type, ignore the second to last EndObject call (depth_ + // == -1) + if (ow_ != NULL && (!has_injected_value_message_ || depth_ >= 0)) { + ow_->EndObject(); + } + // A negative depth_ implies that we have reached the end of Any + // object. Now we write out its contents. + if (depth_ < 0) { + WriteAny(); + return false; + } + return true; +} + +void ProtoStreamObjectWriter::AnyWriter::StartList(StringPiece name) { + ++depth_; + // We expect ow_ to be present as this call only makes sense inside an Any. + if (ow_ == NULL) { + if (!invalid_) { + parent_->InvalidValue("Any", + StrCat("Missing or invalid @type for any field in ", + parent_->master_type_.name())); + invalid_ = true; + } + } else { + ow_->StartList(name); + } +} + +void ProtoStreamObjectWriter::AnyWriter::EndList() { + --depth_; + if (depth_ < 0) { + GOOGLE_LOG(DFATAL) << "Mismatched EndList found, should not be possible"; + depth_ = 0; + } + // We don't write an error on the close, only on the open + if (ow_ != NULL) { + ow_->EndList(); + } +} + +void ProtoStreamObjectWriter::AnyWriter::RenderDataPiece( + StringPiece name, const DataPiece& value) { + // Start an Any only at depth_ 0. Other RenderDataPiece calls with "@type" + // should go to the contained ow_ as they indicate nested Anys. + if (depth_ == 0 && ow_ == NULL && name == "@type") { + StartAny(value); + } else if (ow_ == NULL) { + if (!invalid_) { + parent_->InvalidValue("Any", + StrCat("Missing or invalid @type for any field in ", + parent_->master_type_.name())); + invalid_ = true; + } + } else { + // Check to see if the data needs to be rendered with well-known-type + // renderer. + const TypeRenderer* type_renderer = + FindTypeRenderer(GetFullTypeWithUrl(ow_->master_type_.name())); + if (type_renderer) { + // TODO(rikka): Don't just ignore the util::Status object! + (*type_renderer)(ow_.get(), value); + } else { + ow_->RenderDataPiece(name, value); + } + } +} + +void ProtoStreamObjectWriter::AnyWriter::StartAny(const DataPiece& value) { + // Figure out the type url. This is a copy-paste from WriteString but we also + // need the value, so we can't just call through to that. + if (value.type() == DataPiece::TYPE_STRING) { + type_url_ = value.str().ToString(); + } else { + StatusOr<string> s = value.ToString(); + if (!s.ok()) { + parent_->InvalidValue("String", s.status().error_message()); + invalid_ = true; + return; + } + type_url_ = s.ValueOrDie(); + } + // Resolve the type url, and report an error if we failed to resolve it. + StatusOr<const google::protobuf::Type*> resolved_type = + parent_->typeinfo_->ResolveTypeUrl(type_url_); + if (!resolved_type.ok()) { + parent_->InvalidValue("Any", resolved_type.status().error_message()); + invalid_ = true; + return; + } + // At this point, type is never null. + const google::protobuf::Type* type = resolved_type.ValueOrDie(); + + // If this is the case of an Any in an Any or Struct in an Any, we need to + // expect a StartObject call with "value" while we're at depth_ 0, which we + // should ignore (not propagate to our nested object writer). We also need to + // ignore the second-to-last EndObject call, and not propagate that either. + if (type->name() == kAnyType || type->name() == kStructType) { + has_injected_value_message_ = true; + } + + // Create our object writer and initialize it with the first StartObject + // call. + ow_.reset(new ProtoStreamObjectWriter(parent_->typeinfo_, *type, &output_, + parent_->listener_)); + ow_->StartObject(""); +} + +void ProtoStreamObjectWriter::AnyWriter::WriteAny() { + if (ow_ == NULL) { + // If we had no object writer, we never got any content, so just return + // immediately, which is equivalent to writing an empty Any. + return; + } + // Render the type_url and value fields directly to the stream. + // type_url has tag 1 and value has tag 2. + WireFormatLite::WriteString(1, type_url_, parent_->stream_.get()); + if (!data_.empty()) { + WireFormatLite::WriteBytes(2, data_, parent_->stream_.get()); + } +} + +ProtoStreamObjectWriter::ProtoElement::ProtoElement( + TypeInfo* typeinfo, const google::protobuf::Type& type, + ProtoStreamObjectWriter* enclosing) + : BaseElement(NULL), + ow_(enclosing), + any_(), + field_(NULL), + typeinfo_(typeinfo), + type_(type), + required_fields_(GetRequiredFields(type)), + is_repeated_type_(false), + size_index_(-1), + array_index_(-1), + element_type_(GetElementType(type_)) { + if (element_type_ == ANY) { + any_.reset(new AnyWriter(ow_)); + } +} + +ProtoStreamObjectWriter::ProtoElement::ProtoElement( + ProtoStreamObjectWriter::ProtoElement* parent, + const google::protobuf::Field* field, const google::protobuf::Type& type, + ElementType element_type) + : BaseElement(parent), + ow_(this->parent()->ow_), + any_(), + field_(field), + typeinfo_(this->parent()->typeinfo_), + type_(type), + is_repeated_type_(element_type == ProtoElement::LIST || + element_type == ProtoElement::STRUCT_LIST || + element_type == ProtoElement::MAP || + element_type == ProtoElement::STRUCT_MAP), + size_index_(!is_repeated_type_ && + field->kind() == + google::protobuf::Field_Kind_TYPE_MESSAGE + ? ow_->size_insert_.size() + : -1), + array_index_(is_repeated_type_ ? 0 : -1), + element_type_(element_type) { + if (!is_repeated_type_) { + if (field->cardinality() == + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) { + // Update array_index_ if it is an explicit list. + if (this->parent()->array_index_ >= 0) this->parent()->array_index_++; + } else { + this->parent()->RegisterField(field); + } + if (field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) { + required_fields_ = GetRequiredFields(type_); + int start_pos = ow_->stream_->ByteCount(); + // length of serialized message is the final buffer position minus + // starting buffer position, plus length adjustments for size fields + // of any nested messages. We start with -start_pos here, so we only + // need to add the final buffer position to it at the end. + SizeInfo info = {start_pos, -start_pos}; + ow_->size_insert_.push_back(info); + } + } + if (element_type == ANY) { + any_.reset(new AnyWriter(ow_)); + } +} + +ProtoStreamObjectWriter::ProtoElement* +ProtoStreamObjectWriter::ProtoElement::pop() { + // Calls the registered error listener for any required field(s) not yet + // seen. + for (set<const google::protobuf::Field*>::iterator it = + required_fields_.begin(); + it != required_fields_.end(); ++it) { + ow_->MissingField((*it)->name()); + } + // Computes the total number of proto bytes used by a message, also adjusts + // the size of all parent messages by the length of this size field. + // If size_index_ < 0, this is not a message, so no size field is added. + if (size_index_ >= 0) { + // Add the final buffer position to compute the total length of this + // serialized message. The stored value (before this addition) already + // contains the total length of the size fields of all nested messages + // minus the initial buffer position. + ow_->size_insert_[size_index_].size += ow_->stream_->ByteCount(); + // Calculate the length required to serialize the size field of the + // message, and propagate this additional size information upward to + // all enclosing messages. + int size = ow_->size_insert_[size_index_].size; + int length = CodedOutputStream::VarintSize32(size); + for (ProtoElement* e = parent(); e != NULL; e = e->parent()) { + // Only nested messages have size field, lists do not have size field. + if (e->size_index_ >= 0) { + ow_->size_insert_[e->size_index_].size += length; + } + } + } + return BaseElement::pop<ProtoElement>(); +} + +void ProtoStreamObjectWriter::ProtoElement::RegisterField( + const google::protobuf::Field* field) { + if (!required_fields_.empty() && + field->cardinality() == + google::protobuf::Field_Cardinality_CARDINALITY_REQUIRED) { + required_fields_.erase(field); + } +} + +string ProtoStreamObjectWriter::ProtoElement::ToString() const { + if (parent() == NULL) return ""; + string loc = parent()->ToString(); + if (field_->cardinality() != + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED || + parent()->field_ != field_) { + string name = field_->name(); + int i = 0; + while (i < name.size() && (ascii_isalnum(name[i]) || name[i] == '_')) ++i; + if (i > 0 && i == name.size()) { // safe field name + if (loc.empty()) { + loc = name; + } else { + StrAppend(&loc, ".", name); + } + } else { + StrAppend(&loc, "[\"", CEscape(name), "\"]"); + } + } + if (field_->cardinality() == + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED && + array_index_ > 0) { + StrAppend(&loc, "[", array_index_ - 1, "]"); + } + return loc.empty() ? "." : loc; +} + +inline void ProtoStreamObjectWriter::InvalidName(StringPiece unknown_name, + StringPiece message) { + listener_->InvalidName(location(), ToSnakeCase(unknown_name), message); +} + +inline void ProtoStreamObjectWriter::InvalidValue(StringPiece type_name, + StringPiece value) { + listener_->InvalidValue(location(), type_name, value); +} + +inline void ProtoStreamObjectWriter::MissingField(StringPiece missing_name) { + listener_->MissingField(location(), missing_name); +} + +ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject( + StringPiece name) { + // Starting the root message. Create the root ProtoElement and return. + if (element_ == NULL) { + if (!name.empty()) { + InvalidName(name, "Root element should not be named."); + } + element_.reset(new ProtoElement(typeinfo_, master_type_, this)); + + // If master type is a special type that needs extra values to be written to + // stream, we write those values. + if (master_type_.name() == kStructType) { + StartStruct(NULL); + } else if (master_type_.name() == kStructValueType) { + // We got a StartObject call with google.protobuf.Value field. This means + // we are starting an object within google.protobuf.Value type. The only + // object within that type is a struct type. So start a struct. + const google::protobuf::Field* field = StartStructValueInStruct(NULL); + StartStruct(field); + } + return this; + } + + const google::protobuf::Field* field = NULL; + if (element_ != NULL && element_->IsAny()) { + element_->any()->StartObject(name); + return this; + } else if (element_ != NULL && + (element_->IsMap() || element_->IsStructMap())) { + field = StartMapEntry(name); + if (element_->IsStructMapEntry()) { + // If the top element is a map entry, this means we are starting another + // struct within a struct. + field = StartStructValueInStruct(field); + } + } else if (element_ != NULL && element_->IsStructList()) { + // If the top element is a list, then we are starting a list field within a + // struct. + field = Lookup(name); + field = StartStructValueInStruct(field); + } else { + field = BeginNamed(name, false); + } + if (field == NULL) { + return this; + } + + const google::protobuf::Type* type = LookupType(field); + if (type == NULL) { + ++invalid_depth_; + InvalidName(name, + StrCat("Missing descriptor for field: ", field->type_url())); + return this; + } + + if (field->type_url() == GetFullTypeWithUrl(kStructType)) { + // Start a struct object. + StartStruct(field); + } else if (field->type_url() == GetFullTypeWithUrl(kStructValueType)) { + // We got a StartObject call with google.protobuf.Value field. This means we + // are starting an object within google.protobuf.Value type. The only object + // within that type is a struct type. So start a struct. + field = StartStructValueInStruct(field); + StartStruct(field); + } else if (field->type_url() == GetFullTypeWithUrl(kAnyType)) { + // Begin an Any. We can't do the real work till we get the @type field. + WriteTag(*field); + element_.reset( + new ProtoElement(element_.release(), field, *type, ProtoElement::ANY)); + } else if (IsMap(*field)) { + // Begin a map. + // A map is triggered by a StartObject() call if the current field has a map + // type. Map values are written to proto in a manner detailed in comments + // above StartMapEntry() function. + element_.reset( + new ProtoElement(element_.release(), field, *type, ProtoElement::MAP)); + } else { + WriteTag(*field); + element_.reset(new ProtoElement(element_.release(), field, *type, + ProtoElement::MESSAGE)); + } + return this; +} + +// Proto3 maps are represented on the wire as a message with +// "key" and a "value". +// +// For example, the syntax: +// map<key_type, value_type> map_field = N; +// +// is represented as: +// message MapFieldEntry { +// option map_entry = true; // marks the map construct in the descriptor +// +// key_type key = 1; +// value_type value = 2; +// } +// repeated MapFieldEntry map_field = N; +// +// See go/proto3-maps for more information. +const google::protobuf::Field* ProtoStreamObjectWriter::StartMapEntry( + StringPiece name) { + // top of stack is already a map field + const google::protobuf::Field* field = element_->field(); + const google::protobuf::Type& type = element_->type(); + // If we come from a regular map, use MAP_ENTRY or if we come from a struct, + // use STRUCT_MAP_ENTRY. These values are used later in StartObject/StartList + // or RenderDataPiece for making appropriate decisions. + ProtoElement::ElementType element_type = element_->IsStructMap() + ? ProtoElement::STRUCT_MAP_ENTRY + : ProtoElement::MAP_ENTRY; + WriteTag(*field); + element_.reset( + new ProtoElement(element_.release(), field, type, element_type)); + RenderDataPiece("key", DataPiece(name)); + return BeginNamed("value", false); +} + +// Starts a google.protobuf.Struct. +// 'field' represents a field in a message of type google.protobuf.Struct. A +// struct contains a map with name 'fields'. This function starts this map as +// well. +// When 'field' is NULL, it means that the top level message is of struct +// type. +void ProtoStreamObjectWriter::StartStruct( + const google::protobuf::Field* field) { + const google::protobuf::Type* type = NULL; + if (field) { + type = LookupType(field); + WriteTag(*field); + element_.reset(new ProtoElement(element_.release(), field, *type, + ProtoElement::STRUCT)); + } + const google::protobuf::Field* struct_field = BeginNamed("fields", false); + + if (!struct_field) { + // It is a programmatic error if this happens. Log an error. + GOOGLE_LOG(ERROR) << "Invalid internal state. Cannot find 'fields' within " + << (field ? field->type_url() : "google.protobuf.Struct"); + return; + } + + type = LookupType(struct_field); + element_.reset(new ProtoElement(element_.release(), struct_field, *type, + ProtoElement::STRUCT_MAP)); +} + +// Starts a "struct_value" within struct.proto's google.protobuf.Value type. +// 'field' should be of the type google.protobuf.Value. +// Returns the field identifying "struct_value" within the given field. +// +// If field is NULL, then we are starting struct_value at the top-level, in +// this case skip writing any tag information for the passed field. +const google::protobuf::Field* +ProtoStreamObjectWriter::StartStructValueInStruct( + const google::protobuf::Field* field) { + if (field) { + const google::protobuf::Type* type = LookupType(field); + WriteTag(*field); + element_.reset(new ProtoElement(element_.release(), field, *type, + ProtoElement::STRUCT_VALUE)); + } + return BeginNamed("struct_value", false); +} + +// Starts a "list_value" within struct.proto's google.protobuf.Value type. +// 'field' should be of the type google.protobuf.Value. +// Returns the field identifying "list_value" within the given field. +// +// If field is NULL, then we are starting list_value at the top-level, in +// this case skip writing any tag information for the passed field. +const google::protobuf::Field* ProtoStreamObjectWriter::StartListValueInStruct( + const google::protobuf::Field* field) { + if (field) { + const google::protobuf::Type* type = LookupType(field); + WriteTag(*field); + element_.reset(new ProtoElement(element_.release(), field, *type, + ProtoElement::STRUCT_VALUE)); + } + const google::protobuf::Field* list_value = BeginNamed("list_value", false); + + if (!list_value) { + // It is a programmatic error if this happens. Log an error. + GOOGLE_LOG(ERROR) << "Invalid internal state. Cannot find 'list_value' within " + << (field ? field->type_url() : "google.protobuf.Value"); + return field; + } + + return StartRepeatedValuesInListValue(list_value); +} + +// Starts the repeated "values" field in struct.proto's +// google.protobuf.ListValue type. 'field' should be of type +// google.protobuf.ListValue. +// +// If field is NULL, then we are starting ListValue at the top-level, in +// this case skip writing any tag information for the passed field. +const google::protobuf::Field* +ProtoStreamObjectWriter::StartRepeatedValuesInListValue( + const google::protobuf::Field* field) { + if (field) { + const google::protobuf::Type* type = LookupType(field); + WriteTag(*field); + element_.reset(new ProtoElement(element_.release(), field, *type, + ProtoElement::STRUCT_LIST_VALUE)); + } + return BeginNamed("values", true); +} + +void ProtoStreamObjectWriter::SkipElements() { + if (element_ == NULL) return; + + ProtoElement::ElementType element_type = element_->element_type(); + while (element_type == ProtoElement::STRUCT || + element_type == ProtoElement::STRUCT_LIST_VALUE || + element_type == ProtoElement::STRUCT_VALUE || + element_type == ProtoElement::STRUCT_MAP_ENTRY || + element_type == ProtoElement::MAP_ENTRY) { + element_.reset(element_->pop()); + element_type = + element_ != NULL ? element_->element_type() : ProtoElement::MESSAGE; + } +} + +ProtoStreamObjectWriter* ProtoStreamObjectWriter::EndObject() { + if (invalid_depth_ > 0) { + --invalid_depth_; + return this; + } + if (element_ != NULL && element_->IsAny()) { + if (element_->any()->EndObject()) { + return this; + } + } + if (element_ != NULL) { + element_.reset(element_->pop()); + } + + // Skip sentinel elements added to keep track of new proto3 types - map, + // struct. + SkipElements(); + + // If ending the root element, + // then serialize the full message with calculated sizes. + if (element_ == NULL) { + WriteRootMessage(); + } + return this; +} + +ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList(StringPiece name) { + const google::protobuf::Field* field = NULL; + // Since we cannot have a top-level repeated item in protobuf, the only way + // element_ can be null when here is when we start a top-level list + // google.protobuf.ListValue. + if (element_ == NULL) { + if (!name.empty()) { + InvalidName(name, "Root element should not be named."); + } + element_.reset(new ProtoElement(typeinfo_, master_type_, this)); + + // If master type is a special type that needs extra values to be written to + // stream, we write those values. + if (master_type_.name() == kStructValueType) { + // We got a StartList with google.protobuf.Value master type. This means + // we have to start the "list_value" within google.protobuf.Value. + field = StartListValueInStruct(NULL); + } else if (master_type_.name() == kStructListValueType) { + // We got a StartList with google.protobuf.ListValue master type. This + // means we have to start the "values" within google.protobuf.ListValue. + field = StartRepeatedValuesInListValue(NULL); + } + + // field is NULL when master_type_ is anything other than + // google.protobuf.Value or google.protobuf.ListValue. + if (field) { + const google::protobuf::Type* type = LookupType(field); + element_.reset(new ProtoElement(element_.release(), field, *type, + ProtoElement::STRUCT_LIST)); + } + return this; + } + + if (element_->IsAny()) { + element_->any()->StartList(name); + return this; + } + // The type of element we push to stack. + ProtoElement::ElementType element_type = ProtoElement::LIST; + + // Check if we need to start a map. This can heppen when there is either a map + // or a struct type within a list. + if (element_->IsMap() || element_->IsStructMap()) { + field = StartMapEntry(name); + if (field == NULL) return this; + + if (element_->IsStructMapEntry()) { + // If the top element is a map entry, this means we are starting a list + // within a struct or a map. + // An example sequence of calls would be + // StartObject -> StartList + field = StartListValueInStruct(field); + if (field == NULL) return this; + } + + element_type = ProtoElement::STRUCT_LIST; + } else if (element_->IsStructList()) { + // If the top element is a STRUCT_LIST, this means we are starting a list + // within the current list (inside a struct). + // An example call sequence would be + // StartObject -> StartList -> StartList + // with StartObject starting a struct. + + // Lookup the last list type in element stack as we are adding an element of + // the same type. + field = Lookup(name); + if (field == NULL) return this; + + field = StartListValueInStruct(field); + if (field == NULL) return this; + + element_type = ProtoElement::STRUCT_LIST; + } else { + // Lookup field corresponding to 'name'. If it is a google.protobuf.Value + // or google.protobuf.ListValue type, then StartList is a valid call, start + // this list. + // We cannot use Lookup() here as it will produce InvalidName() error if the + // field is not found. We do not want to error here as it would cause us to + // report errors twice, once here and again later in BeginNamed() call. + // Also we ignore if the field is not found here as it is caught later. + field = typeinfo_->FindField(&element_->type(), name); + + // It is an error to try to bind to map, which behind the scenes is a list. + if (field && IsMap(*field)) { + // Push field to stack for error location tracking & reporting. + element_.reset(new ProtoElement(element_.release(), field, + *LookupType(field), + ProtoElement::MESSAGE)); + InvalidValue("Map", "Cannot bind a list to map."); + ++invalid_depth_; + element_->pop(); + return this; + } + + if (field && field->type_url() == GetFullTypeWithUrl(kStructValueType)) { + // There are 2 cases possible: + // a. g.p.Value is repeated + // b. g.p.Value is not repeated + // + // For case (a), the StartList should bind to the repeated g.p.Value. + // For case (b), the StartList should bind to g.p.ListValue within the + // g.p.Value. + // + // This means, for case (a), we treat it just like any other repeated + // message, except we would apply an appropriate element_type so future + // Start or Render calls are routed appropriately. + if (field->cardinality() != + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) { + field = StartListValueInStruct(field); + } + element_type = ProtoElement::STRUCT_LIST; + } else if (field && + field->type_url() == GetFullTypeWithUrl(kStructListValueType)) { + // We got a StartList with google.protobuf.ListValue master type. This + // means we have to start the "values" within google.protobuf.ListValue. + field = StartRepeatedValuesInListValue(field); + } else { + // If no special types are to be bound, fall back to normal processing of + // StartList. + field = BeginNamed(name, true); + } + if (field == NULL) return this; + } + + const google::protobuf::Type* type = LookupType(field); + if (type == NULL) { + ++invalid_depth_; + InvalidName(name, + StrCat("Missing descriptor for field: ", field->type_url())); + return this; + } + + element_.reset( + new ProtoElement(element_.release(), field, *type, element_type)); + return this; +} + +ProtoStreamObjectWriter* ProtoStreamObjectWriter::EndList() { + if (invalid_depth_ > 0) { + --invalid_depth_; + } else if (element_ != NULL) { + if (element_->IsAny()) { + element_->any()->EndList(); + } else { + element_.reset(element_->pop()); + // Skip sentinel elements added to keep track of new proto3 types - map, + // struct. + SkipElements(); + } + } + + // When element_ is NULL, we have reached the root message type. Write out + // the bytes. + if (element_ == NULL) { + WriteRootMessage(); + } + return this; +} + +Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow, + const DataPiece& data) { + string struct_field_name; + switch (data.type()) { + // Our JSON parser parses numbers as either int64, uint64, or double. + case DataPiece::TYPE_INT64: + case DataPiece::TYPE_UINT64: + case DataPiece::TYPE_DOUBLE: { + struct_field_name = "number_value"; + break; + } + case DataPiece::TYPE_STRING: { + struct_field_name = "string_value"; + break; + } + case DataPiece::TYPE_BOOL: { + struct_field_name = "bool_value"; + break; + } + case DataPiece::TYPE_NULL: { + struct_field_name = "null_value"; + break; + } + default: { + return Status(INVALID_ARGUMENT, + "Invalid struct data type. Only number, string, boolean or " + "null values are supported."); + } + } + ow->RenderDataPiece(struct_field_name, data); + return Status::OK; +} + +Status ProtoStreamObjectWriter::RenderTimestamp(ProtoStreamObjectWriter* ow, + const DataPiece& data) { + if (data.type() != DataPiece::TYPE_STRING) { + return Status(INVALID_ARGUMENT, + StrCat("Invalid data type for timestamp, value is ", + data.ValueAsStringOrDefault(""))); + } + + StringPiece value(data.str()); + + int64 seconds; + int32 nanos; + if (!::google::protobuf::internal::ParseTime(value.ToString(), &seconds, + &nanos)) { + return Status(INVALID_ARGUMENT, StrCat("Invalid time format: ", value)); + } + + + ow->RenderDataPiece("seconds", DataPiece(seconds)); + ow->RenderDataPiece("nanos", DataPiece(nanos)); + return Status::OK; +} + +static inline util::Status RenderOneFieldPath(ProtoStreamObjectWriter* ow, + StringPiece path) { + ow->RenderDataPiece("paths", + DataPiece(ConvertFieldMaskPath(path, &ToSnakeCase))); + return Status::OK; +} + +Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow, + const DataPiece& data) { + if (data.type() != DataPiece::TYPE_STRING) { + return Status(INVALID_ARGUMENT, + StrCat("Invalid data type for field mask, value is ", + data.ValueAsStringOrDefault(""))); + } + + // TODO(tsun): figure out how to do proto descriptor based snake case + // conversions as much as possible. Because ToSnakeCase sometimes returns the + // wrong value. + google::protobuf::scoped_ptr<ResultCallback1<util::Status, StringPiece> > callback( + NewPermanentCallback(&RenderOneFieldPath, ow)); + return DecodeCompactFieldMaskPaths(data.str(), callback.get()); +} + +Status ProtoStreamObjectWriter::RenderDuration(ProtoStreamObjectWriter* ow, + const DataPiece& data) { + if (data.type() != DataPiece::TYPE_STRING) { + return Status(INVALID_ARGUMENT, + StrCat("Invalid data type for duration, value is ", + data.ValueAsStringOrDefault(""))); + } + + StringPiece value(data.str()); + + if (!value.ends_with("s")) { + return Status(INVALID_ARGUMENT, + "Illegal duration format; duration must end with 's'"); + } + value = value.substr(0, value.size() - 1); + int sign = 1; + if (value.starts_with("-")) { + sign = -1; + value = value.substr(1); + } + + StringPiece s_secs, s_nanos; + SplitSecondsAndNanos(value, &s_secs, &s_nanos); + uint64 unsigned_seconds; + if (!safe_strtou64(s_secs, &unsigned_seconds)) { + return Status(INVALID_ARGUMENT, + "Invalid duration format, failed to parse seconds"); + } + + double d_nanos = 0; + if (!safe_strtod("0." + s_nanos.ToString(), &d_nanos)) { + return Status(INVALID_ARGUMENT, + "Invalid duration format, failed to parse nanos seconds"); + } + + int32 nanos = sign * static_cast<int32>(d_nanos * kNanosPerSecond); + int64 seconds = sign * unsigned_seconds; + + if (seconds > kMaxSeconds || seconds < kMinSeconds || + nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) { + return Status(INVALID_ARGUMENT, "Duration value exceeds limits"); + } + + ow->RenderDataPiece("seconds", DataPiece(seconds)); + ow->RenderDataPiece("nanos", DataPiece(nanos)); + return Status::OK; +} + +Status ProtoStreamObjectWriter::RenderWrapperType(ProtoStreamObjectWriter* ow, + const DataPiece& data) { + ow->RenderDataPiece("value", data); + return Status::OK; +} + +ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece( + StringPiece name, const DataPiece& data) { + Status status; + if (invalid_depth_ > 0) return this; + if (element_ != NULL && element_->IsAny()) { + element_->any()->RenderDataPiece(name, data); + return this; + } + + const google::protobuf::Field* field = NULL; + string type_url; + bool is_map_entry = false; + if (element_ == NULL) { + type_url = GetFullTypeWithUrl(master_type_.name()); + } else { + if (element_->IsMap() || element_->IsStructMap()) { + is_map_entry = true; + field = StartMapEntry(name); + } else { + field = Lookup(name); + } + if (field == NULL) { + return this; + } + type_url = field->type_url(); + } + + // Check if there are any well known type renderers available for type_url. + const TypeRenderer* type_renderer = FindTypeRenderer(type_url); + if (type_renderer != NULL) { + // Push the current element to stack so lookups in type_renderer will + // find the fields. We do an EndObject soon after, which pops this. This is + // safe because all well-known types are messages. + if (element_ == NULL) { + element_.reset(new ProtoElement(typeinfo_, master_type_, this)); + } else { + if (field) { + WriteTag(*field); + const google::protobuf::Type* type = LookupType(field); + element_.reset(new ProtoElement(element_.release(), field, *type, + ProtoElement::MESSAGE)); + } + } + status = (*type_renderer)(this, data); + if (!status.ok()) { + InvalidValue(type_url, + StrCat("Field '", name, "', ", status.error_message())); + } + EndObject(); + return this; + } else if (element_ == NULL) { // no message type found at root + element_.reset(new ProtoElement(typeinfo_, master_type_, this)); + InvalidName(name, "Root element must be a message."); + return this; + } + + if (field == NULL) { + return this; + } + const google::protobuf::Type* type = LookupType(field); + if (type == NULL) { + InvalidName(name, + StrCat("Missing descriptor for field: ", field->type_url())); + return this; + } + + // Whether we should pop at the end. Set to true if the data field is a + // message type, which can happen in case of struct values. + bool should_pop = false; + + RenderSimpleDataPiece(*field, *type, data); + + if (should_pop && element_ != NULL) { + element_.reset(element_->pop()); + } + + if (is_map_entry) { + // Ending map is the same as ending an object. + EndObject(); + } + return this; +} + +void ProtoStreamObjectWriter::RenderSimpleDataPiece( + const google::protobuf::Field& field, const google::protobuf::Type& type, + const DataPiece& data) { + // If we are rendering explicit null values and the backend proto field is not + // of the google.protobuf.NullType type, we do nothing. + if (data.type() == DataPiece::TYPE_NULL && + field.type_url() != kStructNullValueTypeUrl) { + return; + } + + // Pushing a ProtoElement and then pop it off at the end for 2 purposes: + // error location reporting and required field accounting. + element_.reset(new ProtoElement(element_.release(), &field, type, + ProtoElement::MESSAGE)); + + // Make sure that field represents a simple data type. + if (field.kind() == google::protobuf::Field_Kind_TYPE_UNKNOWN || + field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) { + InvalidValue(field.type_url().empty() + ? google::protobuf::Field_Kind_Name(field.kind()) + : field.type_url(), + data.ValueAsStringOrDefault("")); + return; + } + + Status status; + switch (field.kind()) { + case google::protobuf::Field_Kind_TYPE_INT32: { + status = WriteInt32(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_SFIXED32: { + status = WriteSFixed32(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_SINT32: { + status = WriteSInt32(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_FIXED32: { + status = WriteFixed32(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_UINT32: { + status = WriteUInt32(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_INT64: { + status = WriteInt64(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_SFIXED64: { + status = WriteSFixed64(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_SINT64: { + status = WriteSInt64(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_FIXED64: { + status = WriteFixed64(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_UINT64: { + status = WriteUInt64(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_DOUBLE: { + status = WriteDouble(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_FLOAT: { + status = WriteFloat(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_BOOL: { + status = WriteBool(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_BYTES: { + status = WriteBytes(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_STRING: { + status = WriteString(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_ENUM: { + status = WriteEnum(field.number(), data, + typeinfo_->GetEnum(field.type_url()), stream_.get()); + break; + } + default: // TYPE_GROUP or TYPE_MESSAGE + status = Status(INVALID_ARGUMENT, data.ToString().ValueOrDie()); + } + if (!status.ok()) { + InvalidValue(google::protobuf::Field_Kind_Name(field.kind()), + status.error_message()); + } + element_.reset(element_->pop()); +} + +// Map of functions that are responsible for rendering well known type +// represented by the key. +hash_map<string, ProtoStreamObjectWriter::TypeRenderer>* +ProtoStreamObjectWriter::CreateRendererMap() { + google::protobuf::scoped_ptr<hash_map<string, ProtoStreamObjectWriter::TypeRenderer> > + result(new hash_map<string, ProtoStreamObjectWriter::TypeRenderer>()); + (*result)["type.googleapis.com/google.protobuf.Timestamp"] = + &ProtoStreamObjectWriter::RenderTimestamp; + (*result)["type.googleapis.com/google.protobuf.Duration"] = + &ProtoStreamObjectWriter::RenderDuration; + (*result)["type.googleapis.com/google.protobuf.FieldMask"] = + &ProtoStreamObjectWriter::RenderFieldMask; + (*result)["type.googleapis.com/google.protobuf.Double"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.Float"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.Int64"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.UInt64"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.Int32"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.UInt32"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.Bool"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.String"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.Bytes"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.DoubleValue"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.FloatValue"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.Int64Value"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.UInt64Value"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.Int32Value"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.UInt32Value"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.BoolValue"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.StringValue"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.BytesValue"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.Value"] = + &ProtoStreamObjectWriter::RenderStructValue; + return result.release(); +} + +ProtoStreamObjectWriter::TypeRenderer* +ProtoStreamObjectWriter::FindTypeRenderer(const string& type_url) { + static hash_map<string, TypeRenderer>* renderers = CreateRendererMap(); + return FindOrNull(*renderers, type_url); +} + +ProtoStreamObjectWriter::ProtoElement::ElementType +ProtoStreamObjectWriter::GetElementType(const google::protobuf::Type& type) { + if (type.name() == kAnyType) { + return ProtoElement::ANY; + } else if (type.name() == kStructType) { + return ProtoElement::STRUCT; + } else if (type.name() == kStructValueType) { + return ProtoElement::STRUCT_VALUE; + } else if (type.name() == kStructListValueType) { + return ProtoElement::STRUCT_LIST_VALUE; + } else { + return ProtoElement::MESSAGE; + } +} + +const google::protobuf::Field* ProtoStreamObjectWriter::BeginNamed( + StringPiece name, bool is_list) { + if (invalid_depth_ > 0) { + ++invalid_depth_; + return NULL; + } + const google::protobuf::Field* field = Lookup(name); + if (field == NULL) { + ++invalid_depth_; + // InvalidName() already called in Lookup(). + return NULL; + } + if (is_list && + field->cardinality() != + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) { + ++invalid_depth_; + InvalidName(name, "Proto field is not repeating, cannot start list."); + return NULL; + } + return field; +} + +const google::protobuf::Field* ProtoStreamObjectWriter::Lookup( + StringPiece unnormalized_name) { + ProtoElement* e = element(); + if (e == NULL) { + InvalidName(unnormalized_name, "Root element must be a message."); + return NULL; + } + if (unnormalized_name.empty()) { + // Objects in repeated field inherit the same field descriptor. + if (e->field() == NULL) { + InvalidName(unnormalized_name, "Proto fields must have a name."); + } else if (e->field()->cardinality() != + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) { + InvalidName(unnormalized_name, "Proto fields must have a name."); + return NULL; + } + return e->field(); + } + const google::protobuf::Field* field = + typeinfo_->FindField(&e->type(), unnormalized_name); + if (field == NULL) InvalidName(unnormalized_name, "Cannot find field."); + return field; +} + +const google::protobuf::Type* ProtoStreamObjectWriter::LookupType( + const google::protobuf::Field* field) { + return (field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE + ? typeinfo_->GetType(field->type_url()) + : &element_->type()); +} + +// Looks up the oneof struct field based on the data type. +StatusOr<const google::protobuf::Field*> +ProtoStreamObjectWriter::LookupStructField(DataPiece::Type type) { + const google::protobuf::Field* field = NULL; + switch (type) { + // Our JSON parser parses numbers as either int64, uint64, or double. + case DataPiece::TYPE_INT64: + case DataPiece::TYPE_UINT64: + case DataPiece::TYPE_DOUBLE: { + field = Lookup("number_value"); + break; + } + case DataPiece::TYPE_STRING: { + field = Lookup("string_value"); + break; + } + case DataPiece::TYPE_BOOL: { + field = Lookup("bool_value"); + break; + } + case DataPiece::TYPE_NULL: { + field = Lookup("null_value"); + break; + } + default: { return Status(INVALID_ARGUMENT, "Invalid struct data type"); } + } + if (field == NULL) { + return Status(INVALID_ARGUMENT, "Could not lookup struct field"); + } + return field; +} + +void ProtoStreamObjectWriter::WriteRootMessage() { + GOOGLE_DCHECK(!done_); + int curr_pos = 0; + // Calls the destructor of CodedOutputStream to remove any uninitialized + // memory from the Cord before we read it. + stream_.reset(NULL); + const void* data; + int length; + google::protobuf::io::ArrayInputStream input_stream(buffer_.data(), buffer_.size()); + while (input_stream.Next(&data, &length)) { + if (length == 0) continue; + int num_bytes = length; + // Write up to where we need to insert the size field. + // The number of bytes we may write is the smaller of: + // - the current fragment size + // - the distance to the next position where a size field needs to be + // inserted. + if (!size_insert_.empty() && + size_insert_.front().pos - curr_pos < num_bytes) { + num_bytes = size_insert_.front().pos - curr_pos; + } + output_->Append(static_cast<const char*>(data), num_bytes); + if (num_bytes < length) { + input_stream.BackUp(length - num_bytes); + } + curr_pos += num_bytes; + // Insert the size field. + // size_insert_.front(): the next <index, size> pair to be written. + // size_insert_.front().pos: position of the size field. + // size_insert_.front().size: the size (integer) to be inserted. + if (!size_insert_.empty() && curr_pos == size_insert_.front().pos) { + // Varint32 occupies at most 10 bytes. + uint8 insert_buffer[10]; + uint8* insert_buffer_pos = CodedOutputStream::WriteVarint32ToArray( + size_insert_.front().size, insert_buffer); + output_->Append(reinterpret_cast<const char*>(insert_buffer), + insert_buffer_pos - insert_buffer); + size_insert_.pop_front(); + } + } + output_->Flush(); + stream_.reset(new CodedOutputStream(&adapter_)); + done_ = true; +} + +bool ProtoStreamObjectWriter::IsMap(const google::protobuf::Field& field) { + if (field.type_url().empty() || + field.kind() != google::protobuf::Field_Kind_TYPE_MESSAGE || + field.cardinality() != + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) { + return false; + } + const google::protobuf::Type* field_type = + typeinfo_->GetType(field.type_url()); + + return GetBoolOptionOrDefault(field_type->options(), + "google.protobuf.MessageOptions.map_entry", false); +} + +void ProtoStreamObjectWriter::WriteTag(const google::protobuf::Field& field) { + WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( + static_cast<WireFormatLite::FieldType>(field.kind())); + stream_->WriteTag(WireFormatLite::MakeTag(field.number(), wire_type)); +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h new file mode 100644 index 00000000..eb4a59f9 --- /dev/null +++ b/src/google/protobuf/util/internal/protostream_objectwriter.h @@ -0,0 +1,455 @@ +// 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_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__ + +#include <deque> +#include <google/protobuf/stubs/hash.h> +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/util/internal/type_info.h> +#include <google/protobuf/util/internal/datapiece.h> +#include <google/protobuf/util/internal/error_listener.h> +#include <google/protobuf/util/internal/structured_objectwriter.h> +#include <google/protobuf/util/type_resolver.h> +#include <google/protobuf/stubs/bytestream.h> + +namespace google { +namespace protobuf { +namespace io { +class CodedOutputStream; +} // namespace io +} // namespace protobuf + + +namespace protobuf { +class Type; +class Field; +} // namespace protobuf + + +namespace protobuf { +namespace util { +namespace converter { + +class ObjectLocationTracker; + +// An ObjectWriter that can write protobuf bytes directly from writer events. +// +// It also supports streaming. +class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter { + public: + // Constructor. Does not take ownership of any parameter passed in. + ProtoStreamObjectWriter(TypeResolver* type_resolver, + const google::protobuf::Type& type, + strings::ByteSink* output, ErrorListener* listener); + virtual ~ProtoStreamObjectWriter(); + + // ObjectWriter methods. + virtual ProtoStreamObjectWriter* StartObject(StringPiece name); + virtual ProtoStreamObjectWriter* EndObject(); + virtual ProtoStreamObjectWriter* StartList(StringPiece name); + virtual ProtoStreamObjectWriter* EndList(); + virtual ProtoStreamObjectWriter* RenderBool(StringPiece name, + bool value) { + return RenderDataPiece(name, DataPiece(value)); + } + virtual ProtoStreamObjectWriter* RenderInt32(StringPiece name, + int32 value) { + return RenderDataPiece(name, DataPiece(value)); + } + virtual ProtoStreamObjectWriter* RenderUint32(StringPiece name, + uint32 value) { + return RenderDataPiece(name, DataPiece(value)); + } + virtual ProtoStreamObjectWriter* RenderInt64(StringPiece name, + int64 value) { + return RenderDataPiece(name, DataPiece(value)); + } + virtual ProtoStreamObjectWriter* RenderUint64(StringPiece name, + uint64 value) { + return RenderDataPiece(name, DataPiece(value)); + } + virtual ProtoStreamObjectWriter* RenderDouble(StringPiece name, + double value) { + return RenderDataPiece(name, DataPiece(value)); + } + virtual ProtoStreamObjectWriter* RenderFloat(StringPiece name, + float value) { + return RenderDataPiece(name, DataPiece(value)); + } + virtual ProtoStreamObjectWriter* RenderString(StringPiece name, + StringPiece value) { + return RenderDataPiece(name, DataPiece(value)); + } + virtual ProtoStreamObjectWriter* RenderBytes(StringPiece name, + StringPiece value) { + return RenderDataPiece(name, DataPiece(value, false)); + } + virtual ProtoStreamObjectWriter* RenderNull(StringPiece name) { + return RenderDataPiece(name, DataPiece::NullData()); + } + + // Renders a DataPiece 'value' into a field whose wire type is determined + // from the given field 'name'. + ProtoStreamObjectWriter* RenderDataPiece(StringPiece name, + const DataPiece& value); + + // Returns the location tracker to use for tracking locations for errors. + const LocationTrackerInterface& location() { + return element_ != NULL ? *element_ : *tracker_; + } + + // When true, we finished writing to output a complete message. + bool done() const { return done_; } + + private: + // Function that renders a well known type with modified behavior. + typedef util::Status (*TypeRenderer)(ProtoStreamObjectWriter*, + const DataPiece&); + + // Handles writing Anys out using nested object writers and the like. + class LIBPROTOBUF_EXPORT AnyWriter { + public: + explicit AnyWriter(ProtoStreamObjectWriter* parent); + ~AnyWriter(); + + // Passes a StartObject call through to the Any writer. + void StartObject(StringPiece name); + + // Passes an EndObject call through to the Any. Returns true if the any + // handled the EndObject call, false if the Any is now all done and is no + // longer needed. + bool EndObject(); + + // Passes a StartList call through to the Any writer. + void StartList(StringPiece name); + + // Passes an EndList call through to the Any writer. + void EndList(); + + // Renders a data piece on the any. + void RenderDataPiece(StringPiece name, const DataPiece& value); + + private: + // Handles starting up the any once we have a type. + void StartAny(const DataPiece& value); + + // Writes the Any out to the parent writer in its serialized form. + void WriteAny(); + + // The parent of this writer, needed for various bits such as type info and + // the listeners. + ProtoStreamObjectWriter* parent_; + + // The nested object writer, used to write events. + google::protobuf::scoped_ptr<ProtoStreamObjectWriter> ow_; + + // The type_url_ that this Any represents. + string type_url_; + + // Whether this any is invalid. This allows us to only report an invalid + // Any message a single time rather than every time we get a nested field. + bool invalid_; + + // The output data and wrapping ByteSink. + string data_; + strings::StringByteSink output_; + + // The depth within the Any, so we can track when we're done. + int depth_; + + // True if the message type contained in Any has a special "value" message + // injected. This is true for well-known message types like Any or Struct. + bool has_injected_value_message_; + }; + + class LIBPROTOBUF_EXPORT ProtoElement : public BaseElement, public LocationTrackerInterface { + public: + // Indicates the type of element. Special types like LIST, MAP, MAP_ENTRY, + // STRUCT etc. are used to deduce other information based on their position + // on the stack of elements. + enum ElementType { + MESSAGE, // Simple message + LIST, // List/repeated element + MAP, // Proto3 map type + MAP_ENTRY, // Proto3 map message type, with 'key' and 'value' fields + ANY, // Proto3 Any type + STRUCT, // Proto3 struct type + STRUCT_VALUE, // Struct's Value message type + STRUCT_LIST, // List type indicator within a struct + STRUCT_LIST_VALUE, // Struct Value's ListValue message type + STRUCT_MAP, // Struct within a struct type + STRUCT_MAP_ENTRY // Struct map's entry type with 'key' and 'value' + // fields + }; + + // Constructor for the root element. No parent nor field. + ProtoElement(TypeInfo* typeinfo, const google::protobuf::Type& type, + ProtoStreamObjectWriter* enclosing); + + // Constructor for a field of an element. + ProtoElement(ProtoElement* parent, const google::protobuf::Field* field, + const google::protobuf::Type& type, ElementType element_type); + + virtual ~ProtoElement() {} + + // Called just before the destructor for clean up: + // - reports any missing required fields + // - computes the space needed by the size field, and augment the + // length of all parent messages by this additional space. + // - releases and returns the parent pointer. + ProtoElement* pop(); + + // Accessors + const google::protobuf::Field* field() const { return field_; } + const google::protobuf::Type& type() const { return type_; } + + // These functions return true if the element type is corresponding to the + // type in function name. + bool IsMap() { return element_type_ == MAP; } + bool IsStructMap() { return element_type_ == STRUCT_MAP; } + bool IsStructMapEntry() { return element_type_ == STRUCT_MAP_ENTRY; } + bool IsStructList() { return element_type_ == STRUCT_LIST; } + bool IsAny() { return element_type_ == ANY; } + + ElementType element_type() { return element_type_; } + + void RegisterField(const google::protobuf::Field* field); + virtual string ToString() const; + + AnyWriter* any() const { return any_.get(); } + + virtual ProtoElement* parent() const { + return static_cast<ProtoElement*>(BaseElement::parent()); + } + + private: + // Used for access to variables of the enclosing instance of + // ProtoStreamObjectWriter. + ProtoStreamObjectWriter* ow_; + + // A writer for Any objects, handles all Any-related nonsense. + google::protobuf::scoped_ptr<AnyWriter> any_; + + // Describes the element as a field in the parent message. + // field_ is NULL if and only if this element is the root element. + const google::protobuf::Field* field_; + + // TypeInfo to lookup types. + TypeInfo* typeinfo_; + + // Additional variables if this element is a message: + // (Root element is always a message). + // descriptor_ : describes allowed fields in the message. + // required_fields_: set of required fields. + // is_repeated_type_ : true if the element is of type list or map. + // size_index_ : index into ProtoStreamObjectWriter::size_insert_ + // for later insertion of serialized message length. + const google::protobuf::Type& type_; + std::set<const google::protobuf::Field*> required_fields_; + const bool is_repeated_type_; + const int size_index_; + + // Tracks position in repeated fields, needed for LocationTrackerInterface. + int array_index_; + + // The type of this element, see enum for permissible types. + ElementType element_type_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoElement); + }; + + // Container for inserting 'size' information at the 'pos' position. + struct SizeInfo { + const int pos; + int size; + }; + + ProtoStreamObjectWriter(TypeInfo* typeinfo, + const google::protobuf::Type& type, + strings::ByteSink* output, ErrorListener* listener); + + ProtoElement* element() { return element_.get(); } + + // Helper methods for calling ErrorListener. See error_listener.h. + void InvalidName(StringPiece unknown_name, StringPiece message); + void InvalidValue(StringPiece type_name, StringPiece value); + void MissingField(StringPiece missing_name); + + // Common code for BeginObject() and BeginList() that does invalid_depth_ + // bookkeeping associated with name lookup. + const google::protobuf::Field* BeginNamed(StringPiece name, bool is_list); + + // Lookup the field in the current element. Looks in the base descriptor + // and in any extension. This will report an error if the field cannot be + // found or if multiple matching extensions are found. + const google::protobuf::Field* Lookup(StringPiece name); + + // Lookup the field type in the type descriptor. Returns NULL if the type + // is not known. + const google::protobuf::Type* LookupType( + const google::protobuf::Field* field); + + // Looks up the oneof struct Value field depending on the type. + // On failure to find, it returns an appropriate error. + util::StatusOr<const google::protobuf::Field*> LookupStructField( + DataPiece::Type type); + + // Starts an entry in map. This will be called after placing map element at + // the top of the stack. Uses this information to write map entries. + const google::protobuf::Field* StartMapEntry(StringPiece name); + + // Starts a google.protobuf.Struct. + // 'field' is of type google.protobuf.Struct. + // If field is NULL, it indicates that the top-level message is a struct + // type. + void StartStruct(const google::protobuf::Field* field); + + // Starts another struct within a struct. + // 'field' is of type google.protobuf.Value (see struct.proto). + const google::protobuf::Field* StartStructValueInStruct( + const google::protobuf::Field* field); + + // Starts a list within a struct. + // 'field' is of type google.protobuf.ListValue (see struct.proto). + const google::protobuf::Field* StartListValueInStruct( + const google::protobuf::Field* field); + + // Starts the repeated "values" field in struct.proto's + // google.protobuf.ListValue type. 'field' should be of type + // google.protobuf.ListValue. + const google::protobuf::Field* StartRepeatedValuesInListValue( + const google::protobuf::Field* field); + + // Pops sentinel elements off the stack. + void SkipElements(); + + // Write serialized output to the final output ByteSink, inserting all + // the size information for nested messages that are missing from the + // intermediate Cord buffer. + void WriteRootMessage(); + + // Returns true if the field is a map. + bool IsMap(const google::protobuf::Field& field); + + // Returns true if the field is an any. + bool IsAny(const google::protobuf::Field& field); + + // Helper method to write proto tags based on the given field. + void WriteTag(const google::protobuf::Field& field); + + // Helper function to render primitive data types in DataPiece. + void RenderSimpleDataPiece(const google::protobuf::Field& field, + const google::protobuf::Type& type, + const DataPiece& data); + + // Renders google.protobuf.Value in struct.proto. It picks the right oneof + // type based on value's type. + static util::Status RenderStructValue(ProtoStreamObjectWriter* ow, + const DataPiece& value); + + // Renders google.protobuf.Timestamp value. + static util::Status RenderTimestamp(ProtoStreamObjectWriter* ow, + const DataPiece& value); + + // Renders google.protobuf.FieldMask value. + static util::Status RenderFieldMask(ProtoStreamObjectWriter* ow, + const DataPiece& value); + + // Renders google.protobuf.Duration value. + static util::Status RenderDuration(ProtoStreamObjectWriter* ow, + const DataPiece& value); + + // Renders wrapper message types for primitive types in + // google/protobuf/wrappers.proto. + static util::Status RenderWrapperType(ProtoStreamObjectWriter* ow, + const DataPiece& value); + + // Helper functions to create the map and find functions responsible for + // rendering well known types, keyed by type URL. + static hash_map<string, TypeRenderer>* CreateRendererMap(); + static TypeRenderer* FindTypeRenderer(const string& type_url); + + // Returns the ProtoElement::ElementType for the given Type. + static ProtoElement::ElementType GetElementType( + const google::protobuf::Type& type); + + // Variables for describing the structure of the input tree: + // master_type_: descriptor for the whole protobuf message. + // typeinfo_ : the TypeInfo object to lookup types. + const google::protobuf::Type& master_type_; + TypeInfo* typeinfo_; + // Whether we own the typeinfo_ object. + bool own_typeinfo_; + + // Indicates whether we finished writing root message completely. + bool done_; + + // Variable for internal state processing: + // element_ : the current element. + // size_insert_: sizes of nested messages. + // pos - position to insert the size field. + // size - size value to be inserted. + google::protobuf::scoped_ptr<ProtoElement> element_; + std::deque<SizeInfo> size_insert_; + + // Variables for output generation: + // output_ : pointer to an external ByteSink for final user-visible output. + // buffer_ : buffer holding partial message before being ready for output_. + // adapter_ : internal adapter between CodedOutputStream and Cord buffer_. + // stream_ : wrapper for writing tags and other encodings in wire format. + strings::ByteSink* output_; + string buffer_; + google::protobuf::io::StringOutputStream adapter_; + google::protobuf::scoped_ptr<google::protobuf::io::CodedOutputStream> stream_; + + // Variables for error tracking and reporting: + // listener_ : a place to report any errors found. + // invalid_depth_: number of enclosing invalid nested messages. + // tracker_ : the root location tracker interface. + ErrorListener* listener_; + int invalid_depth_; + google::protobuf::scoped_ptr<LocationTrackerInterface> tracker_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__ diff --git a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc new file mode 100644 index 00000000..bd4f29f5 --- /dev/null +++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc @@ -0,0 +1,1513 @@ +// 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/util/internal/protostream_objectwriter.h> + +#include <stddef.h> // For size_t + +#include <google/protobuf/field_mask.pb.h> +#include <google/protobuf/timestamp.pb.h> +#include <google/protobuf/wrappers.pb.h> +#include <google/protobuf/io/zero_copy_stream_impl_lite.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/dynamic_message.h> +#include <google/protobuf/message.h> +#include <google/protobuf/util/internal/mock_error_listener.h> +#include <google/protobuf/util/internal/testdata/books.pb.h> +#include <google/protobuf/util/internal/testdata/field_mask.pb.h> +#include <google/protobuf/util/internal/type_info_test_helper.h> +#include <google/protobuf/util/internal/constants.h> +#include <google/protobuf/stubs/bytestream.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/util/internal/testdata/anys.pb.h> +#include <google/protobuf/util/internal/testdata/maps.pb.h> +#include <google/protobuf/util/internal/testdata/struct.pb.h> +#include <google/protobuf/util/internal/testdata/timestamp_duration.pb.h> +#include <gtest/gtest.h> + + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +using google::protobuf::testing::Author; +using google::protobuf::testing::Book; +using google::protobuf::testing::Book_Data; +using google::protobuf::testing::Primitive; +using google::protobuf::testing::Publisher; +using google::protobuf::Descriptor; +using google::protobuf::DescriptorPool; +using google::protobuf::DynamicMessageFactory; +using google::protobuf::FileDescriptorProto; +using google::protobuf::Message; +using google::protobuf::io::ArrayInputStream; +using strings::GrowingArrayByteSink; +using ::testing::_; +using ::testing::Args; +using google::protobuf::testing::anys::AnyM; +using google::protobuf::testing::anys::AnyOut; +using google::protobuf::testing::FieldMaskTest; +using google::protobuf::testing::maps::MapIn; +using google::protobuf::testing::structs::StructType; +using google::protobuf::testing::timestampduration::TimestampDuration; + + +namespace { +string GetTypeUrl(const Descriptor* descriptor) { + return string(kTypeServiceBaseUrl) + "/" + descriptor->full_name(); +} +} // namespace + +class BaseProtoStreamObjectWriterTest + : public ::testing::TestWithParam<testing::TypeInfoSource> { + protected: + BaseProtoStreamObjectWriterTest() + : helper_(GetParam()), + listener_(), + output_(new GrowingArrayByteSink(1000)), + ow_() {} + + explicit BaseProtoStreamObjectWriterTest(const Descriptor* descriptor) + : helper_(GetParam()), + listener_(), + output_(new GrowingArrayByteSink(1000)), + ow_() { + vector<const Descriptor*> descriptors; + descriptors.push_back(descriptor); + ResetTypeInfo(descriptors); + } + + explicit BaseProtoStreamObjectWriterTest( + vector<const Descriptor*> descriptors) + : helper_(GetParam()), + listener_(), + output_(new GrowingArrayByteSink(1000)), + ow_() { + ResetTypeInfo(descriptors); + } + + void ResetTypeInfo(vector<const Descriptor*> descriptors) { + GOOGLE_CHECK(!descriptors.empty()) << "Must have at least one descriptor!"; + helper_.ResetTypeInfo(descriptors); + ow_.reset(helper_.NewProtoWriter(GetTypeUrl(descriptors[0]), output_.get(), + &listener_)); + } + + virtual ~BaseProtoStreamObjectWriterTest() {} + + void CheckOutput(const Message& expected, int expected_length) { + size_t nbytes; + google::protobuf::scoped_array<char> buffer(output_->GetBuffer(&nbytes)); + if (expected_length >= 0) { + EXPECT_EQ(expected_length, nbytes); + } + string str(buffer.get(), nbytes); + + std::stringbuf str_buf(str, std::ios_base::in); + std::istream istream(&str_buf); + google::protobuf::scoped_ptr<Message> message(expected.New()); + message->ParsePartialFromIstream(&istream); + + EXPECT_EQ(expected.DebugString(), message->DebugString()); + } + + void CheckOutput(const Message& expected) { CheckOutput(expected, -1); } + + const google::protobuf::Type* GetType(const Descriptor* descriptor) { + return helper_.GetTypeInfo()->GetType(GetTypeUrl(descriptor)); + } + + testing::TypeInfoTestHelper helper_; + MockErrorListener listener_; + google::protobuf::scoped_ptr<GrowingArrayByteSink> output_; + google::protobuf::scoped_ptr<ProtoStreamObjectWriter> ow_; +}; + +MATCHER_P(HasObjectLocation, expected, + "Verifies the expected object location") { + string actual = std::tr1::get<0>(arg).ToString(); + if (actual.compare(expected) == 0) return true; + *result_listener << "actual location is: " << actual; + return false; +} + +class ProtoStreamObjectWriterTest : public BaseProtoStreamObjectWriterTest { + protected: + ProtoStreamObjectWriterTest() + : BaseProtoStreamObjectWriterTest(Book::descriptor()) {} + + virtual ~ProtoStreamObjectWriterTest() {} +}; + +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + ProtoStreamObjectWriterTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + +TEST_P(ProtoStreamObjectWriterTest, EmptyObject) { + Book empty; + ow_->StartObject("")->EndObject(); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, SimpleObject) { + string content("My content"); + + Book book; + book.set_title("My Title"); + book.set_length(222); + book.set_content(content); + + ow_->StartObject("") + ->RenderString("title", "My Title") + ->RenderInt32("length", 222) + ->RenderBytes("content", content) + ->EndObject(); + CheckOutput(book); +} + +TEST_P(ProtoStreamObjectWriterTest, SimpleMessage) { + Book book; + book.set_title("Some Book"); + book.set_length(102); + Publisher* publisher = book.mutable_publisher(); + publisher->set_name("My Publisher"); + Author* robert = book.mutable_author(); + robert->set_alive(true); + robert->set_name("robert"); + robert->add_pseudonym("bob"); + robert->add_pseudonym("bobby"); + robert->add_friend_()->set_name("john"); + + ow_->StartObject("") + ->RenderString("title", "Some Book") + ->RenderInt32("length", 102) + ->StartObject("publisher") + ->RenderString("name", "My Publisher") + ->EndObject() + ->StartObject("author") + ->RenderBool("alive", true) + ->RenderString("name", "robert") + ->StartList("pseudonym") + ->RenderString("", "bob") + ->RenderString("", "bobby") + ->EndList() + ->StartList("friend") + ->StartObject("") + ->RenderString("name", "john") + ->EndObject() + ->EndList() + ->EndObject() + ->EndObject(); + CheckOutput(book); +} + +TEST_P(ProtoStreamObjectWriterTest, PrimitiveFromStringConversion) { + Primitive full; + full.set_fix32(101); + full.set_u32(102); + full.set_i32(-103); + full.set_sf32(-104); + full.set_s32(-105); + full.set_fix64(40000000001L); + full.set_u64(40000000002L); + full.set_i64(-40000000003L); + full.set_sf64(-40000000004L); + full.set_s64(-40000000005L); + full.set_str("string1"); + full.set_bytes("Some Bytes"); + full.set_float_(3.14f); + full.set_double_(-4.05L); + full.set_bool_(true); + full.add_rep_fix32(201); + full.add_rep_u32(202); + full.add_rep_i32(-203); + full.add_rep_sf32(-204); + full.add_rep_s32(-205); + full.add_rep_fix64(80000000001L); + full.add_rep_u64(80000000002L); + full.add_rep_i64(-80000000003L); + full.add_rep_sf64(-80000000004L); + full.add_rep_s64(-80000000005L); + full.add_rep_str("string2"); + full.add_rep_bytes("More Bytes"); + full.add_rep_float(6.14f); + full.add_rep_double(-8.05L); + full.add_rep_bool(false); + + ow_.reset(helper_.NewProtoWriter(GetTypeUrl(Primitive::descriptor()), + output_.get(), &listener_)); + + ow_->StartObject("") + ->RenderString("fix32", "101") + ->RenderString("u32", "102") + ->RenderString("i32", "-103") + ->RenderString("sf32", "-104") + ->RenderString("s32", "-105") + ->RenderString("fix64", "40000000001") + ->RenderString("u64", "40000000002") + ->RenderString("i64", "-40000000003") + ->RenderString("sf64", "-40000000004") + ->RenderString("s64", "-40000000005") + ->RenderString("str", "string1") + ->RenderString("bytes", "U29tZSBCeXRlcw==") // "Some Bytes" + ->RenderString("float", "3.14") + ->RenderString("double", "-4.05") + ->RenderString("bool", "true") + ->StartList("rep_fix32") + ->RenderString("", "201") + ->EndList() + ->StartList("rep_u32") + ->RenderString("", "202") + ->EndList() + ->StartList("rep_i32") + ->RenderString("", "-203") + ->EndList() + ->StartList("rep_sf32") + ->RenderString("", "-204") + ->EndList() + ->StartList("rep_s32") + ->RenderString("", "-205") + ->EndList() + ->StartList("rep_fix64") + ->RenderString("", "80000000001") + ->EndList() + ->StartList("rep_u64") + ->RenderString("", "80000000002") + ->EndList() + ->StartList("rep_i64") + ->RenderString("", "-80000000003") + ->EndList() + ->StartList("rep_sf64") + ->RenderString("", "-80000000004") + ->EndList() + ->StartList("rep_s64") + ->RenderString("", "-80000000005") + ->EndList() + ->StartList("rep_str") + ->RenderString("", "string2") + ->EndList() + ->StartList("rep_bytes") + ->RenderString("", "TW9yZSBCeXRlcw==") // "More Bytes" + ->EndList() + ->StartList("rep_float") + ->RenderString("", "6.14") + ->EndList() + ->StartList("rep_double") + ->RenderString("", "-8.05") + ->EndList() + ->StartList("rep_bool") + ->RenderString("", "false") + ->EndList() + ->EndObject(); + CheckOutput(full); +} + +TEST_P(ProtoStreamObjectWriterTest, InfinityInputTest) { + Primitive full; + full.set_double_(std::numeric_limits<double>::infinity()); + full.set_float_(std::numeric_limits<float>::infinity()); + full.set_str("-Infinity"); + + ow_.reset(helper_.NewProtoWriter(GetTypeUrl(Primitive::descriptor()), + output_.get(), &listener_)); + + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT32"), + StringPiece("\"Infinity\""))) + .With(Args<0>(HasObjectLocation("i32"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"), + StringPiece("\"Infinity\""))) + .With(Args<0>(HasObjectLocation("u32"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_SFIXED64"), + StringPiece("\"-Infinity\""))) + .With(Args<0>(HasObjectLocation("sf64"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_BOOL"), + StringPiece("\"Infinity\""))) + .With(Args<0>(HasObjectLocation("bool"))); + + ow_->StartObject("") + ->RenderString("double", "Infinity") + ->RenderString("float", "Infinity") + ->RenderString("i32", "Infinity") + ->RenderString("u32", "Infinity") + ->RenderString("sf64", "-Infinity") + ->RenderString("str", "-Infinity") + ->RenderString("bool", "Infinity") + ->EndObject(); + CheckOutput(full); +} + +TEST_P(ProtoStreamObjectWriterTest, NaNInputTest) { + Primitive full; + full.set_double_(std::numeric_limits<double>::quiet_NaN()); + full.set_float_(std::numeric_limits<float>::quiet_NaN()); + full.set_str("NaN"); + + ow_.reset(helper_.NewProtoWriter(GetTypeUrl(Primitive::descriptor()), + output_.get(), &listener_)); + + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT32"), + StringPiece("\"NaN\""))) + .With(Args<0>(HasObjectLocation("i32"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"), + StringPiece("\"NaN\""))) + .With(Args<0>(HasObjectLocation("u32"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_SFIXED64"), + StringPiece("\"NaN\""))) + .With(Args<0>(HasObjectLocation("sf64"))); + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("TYPE_BOOL"), StringPiece("\"NaN\""))) + .With(Args<0>(HasObjectLocation("bool"))); + + ow_->StartObject("") + ->RenderString("double", "NaN") + ->RenderString("float", "NaN") + ->RenderString("i32", "NaN") + ->RenderString("u32", "NaN") + ->RenderString("sf64", "NaN") + ->RenderString("str", "NaN") + ->RenderString("bool", "NaN") + ->EndObject(); + + CheckOutput(full); +} + +TEST_P(ProtoStreamObjectWriterTest, ImplicitPrimitiveList) { + Book expected; + Author* author = expected.mutable_author(); + author->set_name("The Author"); + author->add_pseudonym("first"); + author->add_pseudonym("second"); + + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "The Author") + ->RenderString("pseudonym", "first") + ->RenderString("pseudonym", "second") + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, + LastWriteWinsOnNonRepeatedPrimitiveFieldWithDuplicates) { + Book expected; + Author* author = expected.mutable_author(); + author->set_name("second"); + + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "first") + ->RenderString("name", "second") + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, ExplicitPrimitiveList) { + Book expected; + Author* author = expected.mutable_author(); + author->set_name("The Author"); + author->add_pseudonym("first"); + author->add_pseudonym("second"); + + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "The Author") + ->StartList("pseudonym") + ->RenderString("", "first") + ->RenderString("", "second") + ->EndList() + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, NonRepeatedExplicitPrimitiveList) { + Book expected; + expected.set_allocated_author(new Author()); + + EXPECT_CALL( + listener_, + InvalidName( + _, StringPiece("name"), + StringPiece("Proto field is not repeating, cannot start list."))) + .With(Args<0>(HasObjectLocation("author"))); + ow_->StartObject("") + ->StartObject("author") + ->StartList("name") + ->RenderString("", "first") + ->RenderString("", "second") + ->EndList() + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, ImplicitMessageList) { + Book expected; + Author* outer = expected.mutable_author(); + outer->set_name("outer"); + outer->set_alive(true); + Author* first = outer->add_friend_(); + first->set_name("first"); + Author* second = outer->add_friend_(); + second->set_name("second"); + + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "outer") + ->RenderBool("alive", true) + ->StartObject("friend") + ->RenderString("name", "first") + ->EndObject() + ->StartObject("friend") + ->RenderString("name", "second") + ->EndObject() + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, + LastWriteWinsOnNonRepeatedMessageFieldWithDuplicates) { + Book expected; + Author* author = expected.mutable_author(); + author->set_name("The Author"); + Publisher* publisher = expected.mutable_publisher(); + publisher->set_name("second"); + + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "The Author") + ->EndObject() + ->StartObject("publisher") + ->RenderString("name", "first") + ->EndObject() + ->StartObject("publisher") + ->RenderString("name", "second") + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, ExplicitMessageList) { + Book expected; + Author* outer = expected.mutable_author(); + outer->set_name("outer"); + outer->set_alive(true); + Author* first = outer->add_friend_(); + first->set_name("first"); + Author* second = outer->add_friend_(); + second->set_name("second"); + + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "outer") + ->RenderBool("alive", true) + ->StartList("friend") + ->StartObject("") + ->RenderString("name", "first") + ->EndObject() + ->StartObject("") + ->RenderString("name", "second") + ->EndObject() + ->EndList() + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, NonRepeatedExplicitMessageList) { + Book expected; + Author* author = expected.mutable_author(); + author->set_name("The Author"); + + EXPECT_CALL( + listener_, + InvalidName( + _, StringPiece("publisher"), + StringPiece("Proto field is not repeating, cannot start list."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "The Author") + ->EndObject() + ->StartList("publisher") + ->StartObject("") + ->RenderString("name", "first") + ->EndObject() + ->StartObject("") + ->RenderString("name", "second") + ->EndObject() + ->EndList() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, UnknownFieldAtRoot) { + Book empty; + + EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"), + StringPiece("Cannot find field."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->StartObject("")->RenderString("unknown", "Nope!")->EndObject(); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, UnknownFieldAtAuthorFriend) { + Book expected; + Author* paul = expected.mutable_author(); + paul->set_name("Paul"); + Author* mark = paul->add_friend_(); + mark->set_name("Mark"); + Author* john = paul->add_friend_(); + john->set_name("John"); + Author* luke = paul->add_friend_(); + luke->set_name("Luke"); + + EXPECT_CALL(listener_, InvalidName(_, StringPiece("address"), + StringPiece("Cannot find field."))) + .With(Args<0>(HasObjectLocation("author.friend[1]"))); + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "Paul") + ->StartList("friend") + ->StartObject("") + ->RenderString("name", "Mark") + ->EndObject() + ->StartObject("") + ->RenderString("name", "John") + ->RenderString("address", "Patmos") + ->EndObject() + ->StartObject("") + ->RenderString("name", "Luke") + ->EndObject() + ->EndList() + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, UnknownObjectAtRoot) { + Book empty; + + EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"), + StringPiece("Cannot find field."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->StartObject("")->StartObject("unknown")->EndObject()->EndObject(); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, UnknownObjectAtAuthor) { + Book expected; + Author* author = expected.mutable_author(); + author->set_name("William"); + author->add_pseudonym("Bill"); + + EXPECT_CALL(listener_, InvalidName(_, StringPiece("wife"), + StringPiece("Cannot find field."))) + .With(Args<0>(HasObjectLocation("author"))); + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "William") + ->StartObject("wife") + ->RenderString("name", "Hilary") + ->EndObject() + ->RenderString("pseudonym", "Bill") + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, UnknownListAtRoot) { + Book empty; + + EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"), + StringPiece("Cannot find field."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->StartObject("")->StartList("unknown")->EndList()->EndObject(); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, UnknownListAtPublisher) { + Book expected; + expected.set_title("Brainwashing"); + Publisher* publisher = expected.mutable_publisher(); + publisher->set_name("propaganda"); + + EXPECT_CALL(listener_, InvalidName(_, StringPiece("alliance"), + StringPiece("Cannot find field."))) + .With(Args<0>(HasObjectLocation("publisher"))); + ow_->StartObject("") + ->StartObject("publisher") + ->RenderString("name", "propaganda") + ->StartList("alliance") + ->EndList() + ->EndObject() + ->RenderString("title", "Brainwashing") + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, MissingRequiredField) { + Book expected; + expected.set_title("My Title"); + expected.set_allocated_publisher(new Publisher()); + + EXPECT_CALL(listener_, MissingField(_, StringPiece("name"))) + .With(Args<0>(HasObjectLocation("publisher"))); + ow_->StartObject("") + ->StartObject("publisher") + ->EndObject() + ->RenderString("title", "My Title") + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, InvalidFieldValueAtRoot) { + Book empty; + + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"), + StringPiece("\"garbage\""))) + .With(Args<0>(HasObjectLocation("length"))); + ow_->StartObject("")->RenderString("length", "garbage")->EndObject(); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, MultipleInvalidFieldValues) { + Book expected; + expected.set_title("My Title"); + + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"), + StringPiece("\"-400\""))) + .With(Args<0>(HasObjectLocation("length"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT64"), + StringPiece("\"3.14\""))) + .With(Args<0>(HasObjectLocation("published"))); + ow_->StartObject("") + ->RenderString("length", "-400") + ->RenderString("published", "3.14") + ->RenderString("title", "My Title") + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, UnnamedFieldAtRoot) { + Book empty; + + EXPECT_CALL(listener_, + InvalidName(_, StringPiece(""), + StringPiece("Proto fields must have a name."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->StartObject("")->RenderFloat("", 3.14)->EndObject(); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, UnnamedFieldAtAuthor) { + Book expected; + expected.set_title("noname"); + expected.set_allocated_author(new Author()); + + EXPECT_CALL(listener_, + InvalidName(_, StringPiece(""), + StringPiece("Proto fields must have a name."))) + .With(Args<0>(HasObjectLocation("author"))); + ow_->StartObject("") + ->StartObject("author") + ->RenderInt32("", 123) + ->EndObject() + ->RenderString("title", "noname") + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, UnnamedListAtRoot) { + Book expected; + expected.set_title("noname"); + + EXPECT_CALL(listener_, + InvalidName(_, StringPiece(""), + StringPiece("Proto fields must have a name."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->StartObject("") + ->StartList("") + ->EndList() + ->RenderString("title", "noname") + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, RootNamedObject) { + Book expected; + expected.set_title("Annie"); + + EXPECT_CALL(listener_, + InvalidName(_, StringPiece("oops"), + StringPiece("Root element should not be named."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->StartObject("oops")->RenderString("title", "Annie")->EndObject(); + CheckOutput(expected, 7); +} + +TEST_P(ProtoStreamObjectWriterTest, RootNamedList) { + Book empty; + + EXPECT_CALL(listener_, + InvalidName(_, StringPiece("oops"), + StringPiece("Root element should not be named."))) + .With(Args<0>(HasObjectLocation(""))); + EXPECT_CALL(listener_, + InvalidName(_, StringPiece(""), + StringPiece("Proto fields must have a name."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->StartList("oops")->RenderString("", "item")->EndList(); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, RootUnnamedField) { + Book empty; + + EXPECT_CALL(listener_, + InvalidName(_, StringPiece(""), + StringPiece("Root element must be a message."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->RenderBool("", true); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, RootNamedField) { + Book empty; + + EXPECT_CALL(listener_, + InvalidName(_, StringPiece("oops"), + StringPiece("Root element must be a message."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->RenderBool("oops", true); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, NullValue) { + Book empty; + + ow_->RenderNull(""); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, NullValueForMessageField) { + Book empty; + + ow_->RenderNull("author"); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, NullValueForPrimitiveField) { + Book empty; + + ow_->RenderNull("length"); + CheckOutput(empty, 0); +} + +class ProtoStreamObjectWriterTimestampDurationTest + : public BaseProtoStreamObjectWriterTest { + protected: + ProtoStreamObjectWriterTimestampDurationTest() { + vector<const Descriptor*> descriptors; + descriptors.push_back(TimestampDuration::descriptor()); + descriptors.push_back(google::protobuf::Timestamp::descriptor()); + descriptors.push_back(google::protobuf::Duration::descriptor()); + ResetTypeInfo(descriptors); + } +}; + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError1) { + TimestampDuration timestamp; + + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece( + "Field 'ts', Illegal timestamp format; timestamps " + "must end with 'Z'"))); + + ow_->StartObject("")->RenderString("ts", "")->EndObject(); + CheckOutput(timestamp); +} + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError2) { + TimestampDuration timestamp; + + EXPECT_CALL( + listener_, + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece( + "Field 'ts', Invalid time format: Failed to parse input"))); + + ow_->StartObject("")->RenderString("ts", "Z")->EndObject(); + CheckOutput(timestamp); +} + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError3) { + TimestampDuration timestamp; + + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece( + "Field 'ts', Invalid time format, failed to parse nano " + "seconds"))); + + ow_->StartObject("") + ->RenderString("ts", "1970-01-01T00:00:00.ABZ") + ->EndObject(); + CheckOutput(timestamp); +} + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError4) { + TimestampDuration timestamp; + + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece("Field 'ts', Timestamp value exceeds limits"))); + + ow_->StartObject("") + ->RenderString("ts", "-8032-10-18T00:00:00.000Z") + ->EndObject(); + CheckOutput(timestamp); +} + +// TODO(skarvaje): Write a test for nanos that exceed limit. Currently, it is +// not possible to construct a test case where nanos exceed limit because of +// floating point arithmetic. + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError1) { + TimestampDuration duration; + + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.Duration"), + StringPiece( + "Field 'dur', Illegal duration format; duration must " + "end with 's'"))); + + ow_->StartObject("")->RenderString("dur", "")->EndObject(); + CheckOutput(duration); +} + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError2) { + TimestampDuration duration; + + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.Duration"), + StringPiece( + "Field 'dur', Invalid duration format, failed to parse " + "seconds"))); + + ow_->StartObject("")->RenderString("dur", "s")->EndObject(); + CheckOutput(duration); +} + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError3) { + TimestampDuration duration; + + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.Duration"), + StringPiece( + "Field 'dur', Invalid duration format, failed to " + "parse nanos seconds"))); + + ow_->StartObject("")->RenderString("dur", "123.DEFs")->EndObject(); + CheckOutput(duration); +} + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError4) { + TimestampDuration duration; + + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.Duration"), + StringPiece("Field 'dur', Duration value exceeds limits"))); + + ow_->StartObject("")->RenderString("dur", "315576000002s")->EndObject(); + CheckOutput(duration); +} + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, + MismatchedTimestampTypeInput) { + TimestampDuration timestamp; + EXPECT_CALL( + listener_, + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece( + "Field 'ts', Invalid data type for timestamp, value is null"))) + .With(Args<0>(HasObjectLocation("ts"))); + ow_->StartObject("")->RenderNull("ts")->EndObject(); + CheckOutput(timestamp); +} + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, + MismatchedDurationTypeInput) { + TimestampDuration duration; + EXPECT_CALL( + listener_, + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Duration"), + StringPiece( + "Field 'dur', Invalid data type for duration, value is null"))) + .With(Args<0>(HasObjectLocation("dur"))); + ow_->StartObject("")->RenderNull("dur")->EndObject(); + CheckOutput(duration); +} + +class ProtoStreamObjectWriterStructTest + : public BaseProtoStreamObjectWriterTest { + protected: + ProtoStreamObjectWriterStructTest() { + vector<const Descriptor*> descriptors; + descriptors.push_back(StructType::descriptor()); + descriptors.push_back(google::protobuf::Struct::descriptor()); + ResetTypeInfo(descriptors); + } +}; + +// TODO(skarvaje): Write tests for failure cases. +TEST_P(ProtoStreamObjectWriterStructTest, StructRenderSuccess) { + StructType struct_type; + google::protobuf::Struct* s = struct_type.mutable_object(); + s->mutable_fields()->operator[]("k1").set_number_value(123); + s->mutable_fields()->operator[]("k2").set_bool_value(true); + + ow_->StartObject("") + ->StartObject("object") + ->RenderDouble("k1", 123) + ->RenderBool("k2", true) + ->EndObject() + ->EndObject(); + CheckOutput(struct_type); +} + +TEST_P(ProtoStreamObjectWriterStructTest, StructNullInputSuccess) { + StructType struct_type; + EXPECT_CALL(listener_, + InvalidName(_, StringPiece(""), + StringPiece("Proto fields must have a name."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->StartObject("")->RenderNull("")->EndObject(); + CheckOutput(struct_type); +} + +TEST_P(ProtoStreamObjectWriterStructTest, StructInvalidInputFailure) { + StructType struct_type; + EXPECT_CALL( + listener_, + InvalidValue(_, StringPiece("type.googleapis.com/google.protobuf.Struct"), + StringPiece("true"))) + .With(Args<0>(HasObjectLocation("object"))); + + ow_->StartObject("")->RenderBool("object", true)->EndObject(); + CheckOutput(struct_type); +} + +class ProtoStreamObjectWriterMapTest : public BaseProtoStreamObjectWriterTest { + protected: + ProtoStreamObjectWriterMapTest() + : BaseProtoStreamObjectWriterTest(MapIn::descriptor()) {} +}; + +TEST_P(ProtoStreamObjectWriterMapTest, MapShouldNotAcceptList) { + MapIn mm; + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("Map"), + StringPiece("Cannot bind a list to map."))) + .With(Args<0>(HasObjectLocation("map_input"))); + ow_->StartObject("") + ->StartList("map_input") + ->RenderString("a", "b") + ->EndList() + ->EndObject(); + CheckOutput(mm); +} + +class ProtoStreamObjectWriterAnyTest : public BaseProtoStreamObjectWriterTest { + protected: + ProtoStreamObjectWriterAnyTest() { + vector<const Descriptor*> descriptors; + descriptors.push_back(AnyOut::descriptor()); + descriptors.push_back(google::protobuf::DoubleValue::descriptor()); + descriptors.push_back(google::protobuf::Any::descriptor()); + ResetTypeInfo(descriptors); + } +}; + +TEST_P(ProtoStreamObjectWriterAnyTest, AnyRenderSuccess) { + AnyOut any; + google::protobuf::Any* any_type = any.mutable_any(); + any_type->set_type_url("type.googleapis.com/google.protobuf.DoubleValue"); + google::protobuf::DoubleValue d; + d.set_value(40.2); + any_type->set_value(d.SerializeAsString()); + + ow_->StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/google.protobuf.DoubleValue") + ->RenderDouble("value", 40.2) + ->EndObject() + ->EndObject(); + CheckOutput(any); +} + +TEST_P(ProtoStreamObjectWriterAnyTest, RecursiveAny) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + any->set_type_url("type.googleapis.com/google.protobuf.Any"); + + ::google::protobuf::Any nested_any; + nested_any.set_type_url( + "type.googleapis.com/google.protobuf.testing.anys.AnyM"); + + AnyM m; + m.set_foo("foovalue"); + nested_any.set_value(m.SerializeAsString()); + + any->set_value(nested_any.SerializeAsString()); + + ow_->StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Any") + ->StartObject("value") + ->RenderString("@type", + "type.googleapis.com/google.protobuf.testing.anys.AnyM") + ->RenderString("foo", "foovalue") + ->EndObject() + ->EndObject() + ->EndObject(); + + CheckOutput(out, 115); +} + +TEST_P(ProtoStreamObjectWriterAnyTest, DoubleRecursiveAny) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + any->set_type_url("type.googleapis.com/google.protobuf.Any"); + + ::google::protobuf::Any nested_any; + nested_any.set_type_url("type.googleapis.com/google.protobuf.Any"); + + ::google::protobuf::Any second_nested_any; + second_nested_any.set_type_url( + "type.googleapis.com/google.protobuf.testing.anys.AnyM"); + + AnyM m; + m.set_foo("foovalue"); + second_nested_any.set_value(m.SerializeAsString()); + + nested_any.set_value(second_nested_any.SerializeAsString()); + any->set_value(nested_any.SerializeAsString()); + + ow_->StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Any") + ->StartObject("value") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Any") + ->StartObject("value") + ->RenderString("@type", + "type.googleapis.com/google.protobuf.testing.anys.AnyM") + ->RenderString("foo", "foovalue") + ->EndObject() + ->EndObject() + ->EndObject() + ->EndObject(); + + CheckOutput(out, 159); +} + +TEST_P(ProtoStreamObjectWriterAnyTest, EmptyAnyFromEmptyObject) { + AnyOut out; + out.mutable_any(); + + ow_->StartObject("")->StartObject("any")->EndObject()->EndObject(); + + CheckOutput(out, 2); +} + +TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails1) { + AnyOut any; + + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("Any"), + StringPiece( + "Missing or invalid @type for any field in " + "google.protobuf.testing.anys.AnyOut"))); + + ow_->StartObject("") + ->StartObject("any") + ->StartObject("another") + ->EndObject() + ->EndObject() + ->EndObject(); + CheckOutput(any); +} + +TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails2) { + AnyOut any; + + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("Any"), + StringPiece( + "Missing or invalid @type for any field in " + "google.protobuf.testing.anys.AnyOut"))); + + ow_->StartObject("") + ->StartObject("any") + ->StartList("another") + ->EndObject() + ->EndObject() + ->EndObject(); + CheckOutput(any); +} + +TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails3) { + AnyOut any; + + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("Any"), + StringPiece( + "Missing or invalid @type for any field in " + "google.protobuf.testing.anys.AnyOut"))); + + ow_->StartObject("") + ->StartObject("any") + ->RenderString("value", "somevalue") + ->EndObject() + ->EndObject(); + CheckOutput(any); +} + +TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithInvalidTypeUrlFails) { + AnyOut any; + + EXPECT_CALL( + listener_, + InvalidValue(_, StringPiece("Any"), + StringPiece( + "Invalid type URL, type URLs must be of the form " + "'type.googleapis.com/<typename>', got: " + "type.other.com/some.Type"))); + + ow_->StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.other.com/some.Type") + ->RenderDouble("value", 40.2) + ->EndObject() + ->EndObject(); + CheckOutput(any); +} + +TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithUnknownTypeFails) { + AnyOut any; + + EXPECT_CALL( + listener_, + InvalidValue(_, StringPiece("Any"), + StringPiece("Invalid type URL, unknown type: some.Type"))); + ow_->StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/some.Type") + ->RenderDouble("value", 40.2) + ->EndObject() + ->EndObject(); + CheckOutput(any); +} + +TEST_P(ProtoStreamObjectWriterAnyTest, AnyNullInputFails) { + AnyOut any; + + ow_->StartObject("")->RenderNull("any")->EndObject(); + CheckOutput(any); +} + +class ProtoStreamObjectWriterFieldMaskTest + : public BaseProtoStreamObjectWriterTest { + protected: + ProtoStreamObjectWriterFieldMaskTest() { + vector<const Descriptor*> descriptors; + descriptors.push_back(FieldMaskTest::descriptor()); + descriptors.push_back(google::protobuf::FieldMask::descriptor()); + ResetTypeInfo(descriptors); + } +}; + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, SimpleFieldMaskTest) { + FieldMaskTest expected; + expected.set_id("1"); + expected.mutable_single_mask()->add_paths("path1"); + + ow_->StartObject(""); + ow_->RenderString("id", "1"); + ow_->RenderString("single_mask", "path1"); + ow_->EndObject(); + + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, MutipleMasksInCompactForm) { + FieldMaskTest expected; + expected.set_id("1"); + expected.mutable_single_mask()->add_paths("camel_case1"); + expected.mutable_single_mask()->add_paths("camel_case2"); + expected.mutable_single_mask()->add_paths("camel_case3"); + + ow_->StartObject(""); + ow_->RenderString("id", "1"); + ow_->RenderString("single_mask", "camelCase1,camelCase2,camelCase3"); + ow_->EndObject(); + + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, RepeatedFieldMaskTest) { + FieldMaskTest expected; + expected.set_id("1"); + google::protobuf::FieldMask* mask = expected.add_repeated_mask(); + mask->add_paths("field1"); + mask->add_paths("field2"); + expected.add_repeated_mask()->add_paths("field3"); + + ow_->StartObject(""); + ow_->RenderString("id", "1"); + ow_->StartList("repeated_mask"); + ow_->RenderString("", "field1,field2"); + ow_->RenderString("", "field3"); + ow_->EndList(); + ow_->EndObject(); + + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, EmptyFieldMaskTest) { + FieldMaskTest expected; + expected.set_id("1"); + + ow_->StartObject(""); + ow_->RenderString("id", "1"); + ow_->RenderString("single_mask", ""); + ow_->EndObject(); + + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, MaskUsingApiaryStyleShouldWork) { + FieldMaskTest expected; + expected.set_id("1"); + + ow_->StartObject(""); + ow_->RenderString("id", "1"); + // Case1 + ow_->RenderString("single_mask", + "outerField(camelCase1,camelCase2,camelCase3)"); + expected.mutable_single_mask()->add_paths("outer_field.camel_case1"); + expected.mutable_single_mask()->add_paths("outer_field.camel_case2"); + expected.mutable_single_mask()->add_paths("outer_field.camel_case3"); + + ow_->StartList("repeated_mask"); + + ow_->RenderString("", "a(field1,field2)"); + google::protobuf::FieldMask* mask = expected.add_repeated_mask(); + mask->add_paths("a.field1"); + mask->add_paths("a.field2"); + + ow_->RenderString("", "a(field3)"); + mask = expected.add_repeated_mask(); + mask->add_paths("a.field3"); + + ow_->RenderString("", "a()"); + expected.add_repeated_mask(); + + ow_->RenderString("", "a(,)"); + expected.add_repeated_mask(); + + ow_->RenderString("", "a(field1(field2(field3)))"); + mask = expected.add_repeated_mask(); + mask->add_paths("a.field1.field2.field3"); + + ow_->RenderString("", "a(field1(field2(field3,field4),field5),field6)"); + mask = expected.add_repeated_mask(); + mask->add_paths("a.field1.field2.field3"); + mask->add_paths("a.field1.field2.field4"); + mask->add_paths("a.field1.field5"); + mask->add_paths("a.field6"); + + ow_->RenderString("", "a(id,field1(id,field2(field3,field4),field5),field6)"); + mask = expected.add_repeated_mask(); + mask->add_paths("a.id"); + mask->add_paths("a.field1.id"); + mask->add_paths("a.field1.field2.field3"); + mask->add_paths("a.field1.field2.field4"); + mask->add_paths("a.field1.field5"); + mask->add_paths("a.field6"); + + ow_->RenderString("", "a(((field3,field4)))"); + mask = expected.add_repeated_mask(); + mask->add_paths("a.field3"); + mask->add_paths("a.field4"); + + ow_->EndList(); + ow_->EndObject(); + + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, MoreCloseThanOpenParentheses) { + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.FieldMask"), + StringPiece( + "Field 'single_mask', Invalid FieldMask 'a(b,c))'. " + "Cannot find matching '(' for all ')'."))); + + ow_->StartObject(""); + ow_->RenderString("id", "1"); + ow_->RenderString("single_mask", "a(b,c))"); + ow_->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, MoreOpenThanCloseParentheses) { + EXPECT_CALL( + listener_, + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"), + StringPiece( + "Field 'single_mask', Invalid FieldMask 'a(((b,c)'. Cannot " + "find matching ')' for all '('."))); + + ow_->StartObject(""); + ow_->RenderString("id", "1"); + ow_->RenderString("single_mask", "a(((b,c)"); + ow_->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, PathWithMapKeyShouldWork) { + FieldMaskTest expected; + expected.mutable_single_mask()->add_paths("path.to.map[\"key1\"]"); + expected.mutable_single_mask()->add_paths( + "path.to.map[\"e\\\"[]][scape\\\"\"]"); + expected.mutable_single_mask()->add_paths("path.to.map[\"key2\"]"); + + ow_->StartObject(""); + ow_->RenderString("single_mask", + "path.to.map[\"key1\"],path.to.map[\"e\\\"[]][scape\\\"\"]," + "path.to.map[\"key2\"]"); + ow_->EndObject(); + + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, + MapKeyMustBeAtTheEndOfAPathSegment) { + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.FieldMask"), + StringPiece( + "Field 'single_mask', Invalid FieldMask " + "'path.to.map[\"key1\"]a,path.to.map[\"key2\"]'. " + "Map keys should be at the end of a path segment."))); + + ow_->StartObject(""); + ow_->RenderString("single_mask", + "path.to.map[\"key1\"]a,path.to.map[\"key2\"]"); + ow_->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustEnd) { + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.FieldMask"), + StringPiece( + "Field 'single_mask', Invalid FieldMask " + "'path.to.map[\"key1\"'. Map keys should be " + "represented as [\"some_key\"]."))); + + ow_->StartObject(""); + ow_->RenderString("single_mask", "path.to.map[\"key1\""); + ow_->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustBeEscapedCorrectly) { + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.FieldMask"), + StringPiece( + "Field 'single_mask', Invalid FieldMask " + "'path.to.map[\"ke\"y1\"]'. Map keys should be " + "represented as [\"some_key\"]."))); + + ow_->StartObject(""); + ow_->RenderString("single_mask", "path.to.map[\"ke\"y1\"]"); + ow_->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyCanContainAnyChars) { + FieldMaskTest expected; + expected.mutable_single_mask()->add_paths( + "path.to.map[\"(),[],\\\"'!@#$%^&*123_|War孙天涌,./?><\\\\\"]"); + expected.mutable_single_mask()->add_paths("path.to.map[\"key2\"]"); + + ow_->StartObject(""); + ow_->RenderString( + "single_mask", + "path.to.map[\"(),[],\\\"'!@#$%^&*123_|War孙天涌,./?><\\\\\"]," + "path.to.map[\"key2\"]"); + ow_->EndObject(); + + CheckOutput(expected); +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/snake2camel_objectwriter.h b/src/google/protobuf/util/internal/snake2camel_objectwriter.h new file mode 100644 index 00000000..1a32bc56 --- /dev/null +++ b/src/google/protobuf/util/internal/snake2camel_objectwriter.h @@ -0,0 +1,187 @@ +// 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_UTIL_CONVERTER_SNAKE2CAMEL_OBJECTWRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_SNAKE2CAMEL_OBJECTWRITER_H__ + +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/stringpiece.h> +#include <google/protobuf/util/internal/object_writer.h> +#include <google/protobuf/util/internal/utility.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// Snake2CamelObjectWriter is an ObjectWriter than translates each field name +// from snake_case to camelCase. Typical usage is: +// ProtoStreamObjectSource psos(...); +// JsonObjectWriter jow(...); +// Snake2CamelObjectWriter snake_to_camel(&jow); +// psos.writeTo(&snake_to_camel); +class Snake2CamelObjectWriter : public ObjectWriter { + public: + explicit Snake2CamelObjectWriter(ObjectWriter* ow) + : ow_(ow), normalize_case_(true) {} + virtual ~Snake2CamelObjectWriter() {} + + // ObjectWriter methods. + virtual Snake2CamelObjectWriter* StartObject(StringPiece name) { + ow_->StartObject(ShouldNormalizeCase(name) + ? StringPiece(StringPiece(ToCamelCase(name))) + : name); + return this; + } + + virtual Snake2CamelObjectWriter* EndObject() { + ow_->EndObject(); + return this; + } + + virtual Snake2CamelObjectWriter* StartList(StringPiece name) { + ow_->StartList(ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) + : name); + return this; + } + + virtual Snake2CamelObjectWriter* EndList() { + ow_->EndList(); + return this; + } + + virtual Snake2CamelObjectWriter* RenderBool(StringPiece name, bool value) { + ow_->RenderBool( + ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, + value); + return this; + } + + virtual Snake2CamelObjectWriter* RenderInt32(StringPiece name, int32 value) { + ow_->RenderInt32( + ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, + value); + return this; + } + + virtual Snake2CamelObjectWriter* RenderUint32(StringPiece name, + uint32 value) { + ow_->RenderUint32( + ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, + value); + return this; + } + + virtual Snake2CamelObjectWriter* RenderInt64(StringPiece name, int64 value) { + ow_->RenderInt64( + ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, + value); + return this; + } + + virtual Snake2CamelObjectWriter* RenderUint64(StringPiece name, + uint64 value) { + ow_->RenderUint64( + ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, + value); + return this; + } + + virtual Snake2CamelObjectWriter* RenderDouble(StringPiece name, + double value) { + ow_->RenderDouble( + ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, + value); + return this; + } + + virtual Snake2CamelObjectWriter* RenderFloat(StringPiece name, float value) { + ow_->RenderFloat( + ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, + value); + return this; + } + + virtual Snake2CamelObjectWriter* RenderString(StringPiece name, + StringPiece value) { + ow_->RenderString( + ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, + value); + return this; + } + + virtual Snake2CamelObjectWriter* RenderBytes(StringPiece name, + StringPiece value) { + ow_->RenderBytes( + ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, + value); + return this; + } + + virtual Snake2CamelObjectWriter* RenderNull(StringPiece name) { + ow_->RenderNull(ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) + : name); + return this; + } + + virtual Snake2CamelObjectWriter* DisableCaseNormalizationForNextKey() { + normalize_case_ = false; + return this; + } + + private: + ObjectWriter* ow_; + bool normalize_case_; + + bool ShouldNormalizeCase(StringPiece name) { + if (normalize_case_) { + return !IsCamel(name); + } else { + normalize_case_ = true; + return false; + } + } + + bool IsCamel(StringPiece name) { + return name.empty() || (ascii_islower(name[0]) && !name.contains("_")); + } + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Snake2CamelObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_SNAKE2CAMEL_OBJECTWRITER_H__ diff --git a/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc b/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc new file mode 100644 index 00000000..67388c3b --- /dev/null +++ b/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc @@ -0,0 +1,311 @@ +// 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/util/internal/snake2camel_objectwriter.h> +#include <google/protobuf/util/internal/expecting_objectwriter.h> +#include <gtest/gtest.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +class Snake2CamelObjectWriterTest : public ::testing::Test { + protected: + Snake2CamelObjectWriterTest() : mock_(), expects_(&mock_), testing_(&mock_) {} + virtual ~Snake2CamelObjectWriterTest() {} + + MockObjectWriter mock_; + ExpectingObjectWriter expects_; + Snake2CamelObjectWriter testing_; +}; + +TEST_F(Snake2CamelObjectWriterTest, Empty) { + // Set expectation + expects_.StartObject("")->EndObject(); + + // Actual testing + testing_.StartObject("")->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, UnderscoresOnly) { + // Set expectation + expects_.StartObject("") + ->RenderInt32("", 1) + ->RenderInt32("", 2) + ->RenderInt32("", 3) + ->RenderInt32("", 4) + ->RenderInt32("", 5) + ->EndObject(); + + // Actual testing + testing_.StartObject("") + ->RenderInt32("_", 1) + ->RenderInt32("__", 2) + ->RenderInt32("___", 3) + ->RenderInt32("____", 4) + ->RenderInt32("_____", 5) + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, LowercaseOnly) { + // Set expectation + expects_.StartObject("") + ->RenderString("key", "value") + ->RenderString("abracadabra", "magic") + ->EndObject(); + + // Actual testing + testing_.StartObject("") + ->RenderString("key", "value") + ->RenderString("abracadabra", "magic") + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, UppercaseOnly) { + // Set expectation + expects_.StartObject("") + ->RenderString("key", "VALUE") + ->RenderString("abracadabra", "MAGIC") + ->EndObject(); + + // Actual testing + testing_.StartObject("") + ->RenderString("KEY", "VALUE") + ->RenderString("ABRACADABRA", "MAGIC") + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, CamelCase) { + // Set expectation + expects_.StartObject("") + ->RenderString("camelCase", "camelCase") + ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog", + "theQuickBrownFoxJumpsOverTheLazyDog") + ->EndObject(); + + // Actual testing + testing_.StartObject("") + ->RenderString("camelCase", "camelCase") + ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog", + "theQuickBrownFoxJumpsOverTheLazyDog") + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, FirstCapCamelCase) { + // Sets expectation + expects_.StartObject("camel") + ->RenderString("camelCase", "CamelCase") + ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog", + "TheQuickBrownFoxJumpsOverTheLazyDog") + ->EndObject(); + + // Actual testing + testing_.StartObject("Camel") + ->RenderString("CamelCase", "CamelCase") + ->RenderString("TheQuickBrownFoxJumpsOverTheLazyDog", + "TheQuickBrownFoxJumpsOverTheLazyDog") + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, LastCapCamelCase) { + // Sets expectation + expects_.StartObject("lastCapCamelCasE")->EndObject(); + + // Actual testing + testing_.StartObject("lastCapCamelCasE")->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, MixedCapCamelCase) { + // Sets expectation + expects_.StartObject("googleIsTheBest") + ->RenderFloat("iLoveGOOGLE", 1.61803f) + ->RenderFloat("goGoogleGO", 2.71828f) + ->RenderFloat("gBikeISCool", 3.14159f) + ->EndObject(); + + // Actual testing + testing_.StartObject("GOOGLEIsTheBest") + ->RenderFloat("ILoveGOOGLE", 1.61803f) + ->RenderFloat("GOGoogleGO", 2.71828f) + ->RenderFloat("GBikeISCool", 3.14159f) + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, MixedCase) { + // Sets expectation + expects_.StartObject("snakeCaseCamelCase") + ->RenderBool("camelCaseSnakeCase", false) + ->RenderBool("mixedCamelAndUnderScores", false) + ->RenderBool("goGOOGLEGo", true) + ->EndObject(); + + // Actual testing + testing_.StartObject("snake_case_camelCase") + ->RenderBool("camelCase_snake_case", false) + ->RenderBool("MixedCamel_And_UnderScores", false) + ->RenderBool("Go_GOOGLEGo", true) + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, SnakeCase) { + // Sets expectation + expects_.StartObject("") + ->RenderString("snakeCase", "snake_case") + ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog", + "the_quick_brown_fox_jumps_over_the_lazy_dog") + ->EndObject(); + + // Actual testing + testing_.StartObject("") + ->RenderString("snake_case", "snake_case") + ->RenderString("the_quick_brown_fox_jumps_over_the_lazy_dog", + "the_quick_brown_fox_jumps_over_the_lazy_dog") + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, FirstCapSnakeCase) { + // Sets expectation + expects_.StartObject("firstCapSnakeCase") + ->RenderBool("helloWorld", true) + ->EndObject(); + + // Actual testing + testing_.StartObject("First_Cap_Snake_Case") + ->RenderBool("Hello_World", true) + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, AllCapSnakeCase) { + // Sets expectation + expects_.StartObject("allCAPSNAKECASE") + ->RenderDouble("nyseGOOGL", 600.0L) + ->RenderDouble("aBCDE", 1.0L) + ->RenderDouble("klMNOP", 2.0L) + ->RenderDouble("abcIJKPQRXYZ", 3.0L) + ->EndObject(); + + // Actual testing + testing_.StartObject("ALL_CAP_SNAKE_CASE") + ->RenderDouble("NYSE_GOOGL", 600.0L) + ->RenderDouble("A_B_C_D_E", 1.0L) + ->RenderDouble("KL_MN_OP", 2.0L) + ->RenderDouble("ABC_IJK_PQR_XYZ", 3.0L) + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, RepeatedUnderScoreSnakeCase) { + // Sets expectation + expects_.StartObject("") + ->RenderInt32("doubleUnderscoreSnakeCase", 2) + ->RenderInt32("tripleUnderscoreFirstCap", 3) + ->RenderInt32("quadrupleUNDERSCOREALLCAP", 4) + ->EndObject(); + + // Actual testing + testing_.StartObject("") + ->RenderInt32("double__underscore__snake__case", 2) + ->RenderInt32("Triple___Underscore___First___Cap", 3) + ->RenderInt32("QUADRUPLE____UNDERSCORE____ALL____CAP", 4) + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, LeadingUnderscoreSnakeCase) { + // Sets expectation + expects_.StartObject("leadingUnderscoreSnakeCase") + ->RenderUint32("leadingDoubleUnderscore", 2) + ->RenderUint32("leadingTripleUnderscoreFirstCap", 3) + ->RenderUint32("leadingQUADRUPLEUNDERSCOREALLCAP", 4) + ->EndObject(); + + // Actual testing + testing_.StartObject("_leading_underscore_snake_case") + ->RenderUint32("__leading_double_underscore", 2) + ->RenderUint32("___Leading_Triple_Underscore_First_Cap", 3) + ->RenderUint32("____LEADING_QUADRUPLE_UNDERSCORE_ALL_CAP", 4) + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, TrailingUnderscoreSnakeCase) { + // Sets expectation + expects_.StartObject("trailingUnderscoreSnakeCase") + ->RenderInt64("trailingDoubleUnderscore", 2L) + ->RenderInt64("trailingTripleUnderscoreFirstCap", 3L) + ->RenderInt64("trailingQUADRUPLEUNDERSCOREALLCAP", 4L) + ->EndObject(); + + // Actual testing + testing_.StartObject("trailing_underscore_snake_case") + ->RenderInt64("trailing_double_underscore__", 2L) + ->RenderInt64("Trailing_Triple_Underscore_First_Cap___", 3L) + ->RenderInt64("TRAILING_QUADRUPLE_UNDERSCORE_ALL_CAP____", 4L) + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, EnclosingUnderscoreSnakeCase) { + // Sets expectation + expects_.StartObject("enclosingUnderscoreSnakeCase") + ->RenderUint64("enclosingDoubleUnderscore", 2L) + ->RenderUint64("enclosingTripleUnderscoreFirstCap", 3L) + ->RenderUint64("enclosingQUADRUPLEUNDERSCOREALLCAP", 4L) + ->EndObject(); + + // Actual testing + testing_.StartObject("_enclosing_underscore_snake_case_") + ->RenderUint64("__enclosing_double_underscore__", 2L) + ->RenderUint64("___Enclosing_Triple_Underscore_First_Cap___", 3L) + ->RenderUint64("____ENCLOSING_QUADRUPLE_UNDERSCORE_ALL_CAP____", 4L) + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, DisableCaseNormalizationOnlyDisablesFirst) { + // Sets expectation + expects_.StartObject("") + ->RenderString("snakeCase", "snake_case") + ->RenderString( + "the_quick_brown_fox_jumps_over_the_lazy_dog", // case retained + "the_quick_brown_fox_jumps_over_the_lazy_dog") + ->RenderBool("theSlowFox", true) // disable case not in effect + ->EndObject(); + + // Actual testing + testing_.StartObject("") + ->RenderString("snake_case", "snake_case") + ->DisableCaseNormalizationForNextKey() + ->RenderString("the_quick_brown_fox_jumps_over_the_lazy_dog", + "the_quick_brown_fox_jumps_over_the_lazy_dog") + ->RenderBool("the_slow_fox", true) + ->EndObject(); +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/structured_objectwriter.h b/src/google/protobuf/util/internal/structured_objectwriter.h new file mode 100644 index 00000000..3f065d6b --- /dev/null +++ b/src/google/protobuf/util/internal/structured_objectwriter.h @@ -0,0 +1,118 @@ +// 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_UTIL_CONVERTER_STRUCTURED_OBJECTWRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_STRUCTURED_OBJECTWRITER_H__ + +#include <memory> +#ifndef _SHARED_PTR_H +#include <google/protobuf/stubs/shared_ptr.h> +#endif + +#include <google/protobuf/stubs/casts.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/util/internal/object_writer.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// An StructuredObjectWriter is an ObjectWriter for writing +// tree-structured data in a stream of events representing objects +// and collections. Implementation of this interface can be used to +// write an object stream to an in-memory structure, protobufs, +// JSON, XML, or any other output format desired. The ObjectSource +// interface is typically used as the source of an object stream. +// +// See JsonObjectWriter for a sample implementation of +// StructuredObjectWriter and its use. +// +// Derived classes could be thread-unsafe. +class LIBPROTOBUF_EXPORT StructuredObjectWriter : public ObjectWriter { + public: + virtual ~StructuredObjectWriter() {} + + protected: + // A base element class for subclasses to extend, makes tracking state easier. + // + // StructuredObjectWriter behaves as a visitor. BaseElement represents a node + // in the input tree. Implementation of StructuredObjectWriter should also + // extend BaseElement to keep track of the location in the input tree. + class LIBPROTOBUF_EXPORT BaseElement { + public: + // Takes ownership of the parent Element. + explicit BaseElement(BaseElement* parent) + : parent_(parent), level_(parent == NULL ? 0 : parent->level() + 1) {} + virtual ~BaseElement() {} + + // Releases ownership of the parent and returns a pointer to it. + template <typename ElementType> + ElementType* pop() { + return down_cast<ElementType*>(parent_.release()); + } + + // Returns true if this element is the root. + bool is_root() const { return parent_ == NULL; } + + // Returns the number of hops from this element to the root element. + int level() const { return level_; } + + protected: + // Returns pointer to parent element without releasing ownership. + virtual BaseElement* parent() const { return parent_.get(); } + + private: + // Pointer to the parent Element. + google::protobuf::scoped_ptr<BaseElement> parent_; + + // Number of hops to the root Element. + // The root Element has NULL parent_ and a level_ of 0. + const int level_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(BaseElement); + }; + + StructuredObjectWriter() {} + + // Returns the current element. Used for indentation and name overrides. + virtual BaseElement* element() = 0; + + private: + // Do not add any data members to this class. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StructuredObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_STRUCTURED_OBJECTWRITER_H__ diff --git a/src/google/protobuf/util/internal/testdata/anys.proto b/src/google/protobuf/util/internal/testdata/anys.proto new file mode 100644 index 00000000..18c59cbb --- /dev/null +++ b/src/google/protobuf/util/internal/testdata/anys.proto @@ -0,0 +1,53 @@ +// 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. + +// Proto to test Proto3 Any serialization. +syntax = "proto3"; + +package google.protobuf.testing.anys; +option java_package = "com.google.protobuf.testing.anys"; + +import "google/protobuf/any.proto"; + +message AnyIn { + string something = 1; +} + +message AnyOut { + google.protobuf.Any any = 1; +} + +message AnyM { + string foo = 1; +} + +service TestService { + rpc Call(AnyIn) returns (AnyOut); +} diff --git a/src/google/protobuf/util/internal/testdata/books.proto b/src/google/protobuf/util/internal/testdata/books.proto new file mode 100644 index 00000000..6e2f109b --- /dev/null +++ b/src/google/protobuf/util/internal/testdata/books.proto @@ -0,0 +1,171 @@ +// 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. + +// Author: sven@google.com (Sven Mawson) +// +// Sample protos for testing. +syntax = "proto2"; + +package google.protobuf.testing; + +// A book +message Book { + optional string title = 1; + optional Author author = 2; + optional uint32 length = 3; + optional int64 published = 4; + optional bytes content = 5; + + optional group Data = 6 { + optional uint32 year = 7; + optional string copyright = 8; + } + + message Label { + optional string key = 1; + optional string value = 2; + } + + optional Publisher publisher = 9; + repeated Label labels = 10; + + extensions 200 to 499; +} + +// A publisher of a book, tests required fields. +message Publisher { + required string name = 1; +} + +// An author of a book +message Author { + optional uint64 id = 1; + optional string name = 2; + repeated string pseudonym = 3; + optional bool alive = 4; + repeated Author friend = 5; +} + +// For testing resiliency of our protostream parser. +// Field numbers of Author are reused for something else. +message BadAuthor { + optional string id = 1; // non-length-delimited to length-delimited. + repeated uint64 name = 2; // string to repeated (both length-delimited). + optional string pseudonym = 3; // Repeated to optional. + repeated bool alive = 4 [packed=true]; // Optional to repeated. +} + +// All primitive types +message Primitive { + // 32 bit numbers: + optional fixed32 fix32 = 1; + optional uint32 u32 = 2; + optional int32 i32 = 3; + optional sfixed32 sf32 = 4; + optional sint32 s32 = 5; + + // 64 bit numbers: + optional fixed64 fix64 = 6; + optional uint64 u64 = 7; + optional int64 i64 = 8; + optional sfixed64 sf64 = 9; + optional sint64 s64 = 10; + + // The other stuff. + optional string str = 11; + optional bytes bytes = 12; + optional float float = 13; + optional double double = 14; + optional bool bool = 15; + + // repeated 32 bit numbers: + repeated fixed32 rep_fix32 = 16; + repeated uint32 rep_u32 = 17; + repeated int32 rep_i32 = 18; + repeated sfixed32 rep_sf32 = 19; + repeated sint32 rep_s32 = 20; + + // repeated 64 bit numbers: + repeated fixed64 rep_fix64 = 21; + repeated uint64 rep_u64 = 22; + repeated int64 rep_i64 = 23; + repeated sfixed64 rep_sf64 = 24; + repeated sint64 rep_s64 = 25; + + // repeated other stuff: + repeated string rep_str = 26; + repeated bytes rep_bytes = 27; + repeated float rep_float = 28; + repeated double rep_double = 29; + repeated bool rep_bool = 30; +} + +// Test packed versions of all repeated primitives. +// The field numbers should match their non-packed version in Primitive message. +message PackedPrimitive { + // repeated 32 bit numbers: + repeated fixed32 rep_fix32 = 16 [packed=true]; + repeated uint32 rep_u32 = 17 [packed=true]; + repeated int32 rep_i32 = 18 [packed=true]; + repeated sfixed32 rep_sf32 = 19 [packed=true]; + repeated sint32 rep_s32 = 20 [packed=true]; + + // repeated 64 bit numbers: + repeated fixed64 rep_fix64 = 21 [packed=true]; + repeated uint64 rep_u64 = 22 [packed=true]; + repeated int64 rep_i64 = 23 [packed=true]; + repeated sfixed64 rep_sf64 = 24 [packed=true]; + repeated sint64 rep_s64 = 25 [packed=true]; + + // repeated other stuff: + repeated float rep_float = 28 [packed=true]; + repeated double rep_double = 29 [packed=true]; + repeated bool rep_bool = 30 [packed=true]; +} + +// Test extensions. +extend Book { + repeated Author more_author = 201; +} + +// Test nested extensions. +message NestedBook { + extend Book { + optional NestedBook another_book = 301; + } + // Recurse + optional Book book = 1; +} + +// For testing resiliency of our protostream parser. +// Field number of NestedBook is reused for something else. +message BadNestedBook { + repeated uint32 book = 1 [packed=true]; // Packed to optional message. +} diff --git a/src/google/protobuf/util/internal/testdata/default_value.proto b/src/google/protobuf/util/internal/testdata/default_value.proto new file mode 100644 index 00000000..ecfc8119 --- /dev/null +++ b/src/google/protobuf/util/internal/testdata/default_value.proto @@ -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. + +syntax = "proto3"; + +package google.protobuf.testing; + +import "google/protobuf/any.proto"; +import "google/protobuf/struct.proto"; +import "google/protobuf/wrappers.proto"; + +message DefaultValueTestCases { + DoubleMessage empty_double = 1; + DoubleMessage double_with_default_value = 2; + DoubleMessage double_with_nondefault_value = 3; + DoubleMessage repeated_double = 4; + DoubleMessage nested_message = 5; + DoubleMessage repeated_nested_message = 6; + StructMessage empty_struct = 201; + StructMessage empty_struct2 = 202; + StructMessage struct_with_null_value = 203; + StructMessage struct_with_values = 204; + StructMessage struct_with_nested_struct = 205; + StructMessage struct_with_nested_list = 206; + StructMessage struct_with_list_of_nulls = 207; + StructMessage struct_with_list_of_lists = 208; + StructMessage struct_with_list_of_structs = 209; + google.protobuf.Struct top_level_struct = 210; + ValueMessage value_wrapper_simple = 212; + ValueMessage value_wrapper_with_struct = 213; + ValueMessage value_wrapper_with_list = 214; + ListValueMessage list_value_wrapper = 215; + google.protobuf.Value top_level_value_simple = 216; + google.protobuf.Value top_level_value_with_struct = 217; + google.protobuf.Value top_level_value_with_list = 218; + google.protobuf.ListValue top_level_listvalue = 219; + AnyMessage empty_any = 301; + AnyMessage type_only_any = 302; + AnyMessage recursive_any = 303; + AnyMessage any_with_message_value = 304; + AnyMessage any_with_nested_message = 305; + AnyMessage any_with_message_containing_map = 306; + AnyMessage any_with_message_containing_struct = 307; + google.protobuf.Any top_level_any = 308; + StringtoIntMap empty_map = 401; + StringtoIntMap string_to_int = 402; + IntToStringMap int_to_string = 403; + MixedMap mixed1 = 404; + MixedMap2 mixed2 = 405; + MessageMap map_of_objects = 406; + DoubleValueMessage double_value = 501; + DoubleValueMessage double_value_default = 502; +} + +message DoubleMessage { + double double_value = 1; + repeated double repeated_double = 2; + DoubleMessage nested_message = 3; + repeated DoubleMessage repeated_nested_message = 4; + google.protobuf.DoubleValue double_wrapper = 100; +} + +message StructMessage { + google.protobuf.Struct struct = 1; +} + +message ValueMessage { + google.protobuf.Value value = 1; +} + +message ListValueMessage { + google.protobuf.ListValue shopping_list = 1; +} +message RequestMessage { + string content = 1; +} + +// A test service. +service DefaultValueTestService { + // A test method. + rpc Call(RequestMessage) returns (DefaultValueTestCases); +} + +message AnyMessage { + google.protobuf.Any any = 1; + AnyData data = 2; +} + +message AnyData { + int32 attr = 1; + string str = 2; + repeated string msgs = 3; + AnyData nested_data = 4; + map<string, string> map_data = 7; + google.protobuf.Struct struct_data = 8; + repeated AnyData repeated_data = 9; +} + +message StringtoIntMap { + map<string, int32> map = 1; +} + +message IntToStringMap { + map<int32, string> map = 1; +} + +message MixedMap { + string msg = 1; + map<string, float> map = 2; + int32 int_value = 3; +} + +message MixedMap2 { + enum E { + E0 = 0; + E1 = 1; + E2 = 2; + E3 = 3; + } + map<int32, bool> map = 1; + E ee = 2; + string msg = 4; +} + +message MessageMap { + message M { + int32 inner_int = 1; + string inner_text = 2; + } + map<string, M> map = 1; +} + +message DoubleValueMessage { + google.protobuf.DoubleValue double = 1; +} diff --git a/src/google/protobuf/util/internal/testdata/default_value_test.proto b/src/google/protobuf/util/internal/testdata/default_value_test.proto new file mode 100644 index 00000000..21b85e6d --- /dev/null +++ b/src/google/protobuf/util/internal/testdata/default_value_test.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.testing; + +message DefaultValueTest { + double double_value = 1; + repeated double repeated_double = 2; + float float_value = 3; + int64 int64_value = 5; + uint64 uint64_value = 7; + int32 int32_value = 9; + uint32 uint32_value = 11; + bool bool_value = 13; + string string_value = 15; + bytes bytes_value = 17 [ctype = CORD]; +} diff --git a/src/google/protobuf/util/internal/testdata/field_mask.proto b/src/google/protobuf/util/internal/testdata/field_mask.proto new file mode 100644 index 00000000..e8b2bc5f --- /dev/null +++ b/src/google/protobuf/util/internal/testdata/field_mask.proto @@ -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. + +syntax = "proto3"; + +package google.protobuf.testing; + +import "google/protobuf/field_mask.proto"; + +message NestedFieldMask { + string data = 1; + google.protobuf.FieldMask single_mask = 2; + repeated google.protobuf.FieldMask repeated_mask = 3; +} + +message FieldMaskTest { + string id = 1; + google.protobuf.FieldMask single_mask = 2; + repeated google.protobuf.FieldMask repeated_mask = 3; + repeated NestedFieldMask nested_mask = 4; +} + +message FieldMaskTestCases { + FieldMaskWrapper single_mask = 1; + FieldMaskWrapper multiple_mask = 2; + FieldMaskWrapper snake_camel = 3; + FieldMaskWrapper empty_field = 4; + FieldMaskWrapper apiary_format1 = 5; + FieldMaskWrapper apiary_format2 = 6; + FieldMaskWrapper apiary_format3 = 7; + FieldMaskWrapper map_key1 = 8; + FieldMaskWrapper map_key2 = 9; + FieldMaskWrapper map_key3 = 10; + FieldMaskWrapper map_key4 = 11; + FieldMaskWrapper map_key5 = 12; +} + +message FieldMaskWrapper { + google.protobuf.FieldMask mask = 1; +} + +service FieldMaskTestService { + rpc Call(FieldMaskTestCases) returns (FieldMaskTestCases); +} diff --git a/objectivec/GPBExtensionField.h b/src/google/protobuf/util/internal/testdata/maps.proto index e5ba1561..7fb42a26 100644 --- a/objectivec/GPBExtensionField.h +++ b/src/google/protobuf/util/internal/testdata/maps.proto @@ -28,24 +28,30 @@ // (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> +// Proto to test proto3 maps. +syntax = "proto3"; -#import "GPBWireFormat.h" -#import "GPBTypes.h" +package google.protobuf.testing.maps; +option java_package = "com.google.protobuf.testing.maps"; -@class GPBCodedInputStream; -@class GPBCodedOutputStream; -@class GPBExtensionRegistry; -@class GPBDescriptor; -@class GPBExtensionDescriptor; +message MapIn { + string other = 1; + repeated string things = 2; + map<string, string> map_input = 3; +} -@interface GPBExtensionField : NSObject<NSCopying> +message MapOut { + map<string, MapM> map1 = 1; + map<string, MapOut> map2 = 2; + map<int32, string> map3 = 3; + string bar = 4; +} -@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; +message MapM { + string foo = 1; +} -@end +service TestService { + rpc Call1(MapIn) returns (MapOut); + rpc Call2(MapIn) returns (MapOut); +} diff --git a/objectivec/Tests/Filter1.txt b/src/google/protobuf/util/internal/testdata/struct.proto index 88a5cac8..c15aba0d 100644 --- a/objectivec/Tests/Filter1.txt +++ b/src/google/protobuf/util/internal/testdata/struct.proto @@ -1,5 +1,5 @@ // Protocol Buffers - Google's data interchange format -// Copyright 2014 Google Inc. All rights reserved. +// Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without @@ -28,13 +28,18 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Proto to test proto3 struct. +syntax = "proto3"; -// Test the filter system for the ObjC Protocol Buffer Compiler. +package google.protobuf.testing.structs; +option java_package = "com.google.protobuf.testing.structs"; -// 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). +import "google/protobuf/struct.proto"; -Keep -RemoveEnumMessage_KeepNestedInside -RemoveJustKidding +message StructType { + google.protobuf.Struct object = 1; +} + +service TestService { + rpc Call(StructType) returns (StructType); +} diff --git a/objectivec/Tests/unittest_filter.proto b/src/google/protobuf/util/internal/testdata/timestamp_duration.proto index 1398dfc8..56351f16 100644 --- a/objectivec/Tests/unittest_filter.proto +++ b/src/google/protobuf/util/internal/testdata/timestamp_duration.proto @@ -1,5 +1,6 @@ // Protocol Buffers - Google's data interchange format -// Copyright 2013 Google Inc. All rights reserved. +// 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 @@ -27,45 +28,20 @@ // (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"; +// Proto to test proto3 Timestamp and Duration. +syntax = "proto3"; -package protobuf_unittest; +package google.protobuf.testing.timestampduration; +option java_package = "com.google.protobuf.testing.timestampduration"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/duration.proto"; -message Keep { +message TimestampDuration { + google.protobuf.Timestamp ts = 1; + google.protobuf.Duration dur = 2; } -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 { - } +service TestService { + rpc Call(TimestampDuration) returns (TimestampDuration); } diff --git a/src/google/protobuf/util/internal/testdata/wrappers.proto b/src/google/protobuf/util/internal/testdata/wrappers.proto new file mode 100644 index 00000000..eabc99f2 --- /dev/null +++ b/src/google/protobuf/util/internal/testdata/wrappers.proto @@ -0,0 +1,100 @@ +// 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.testing; + +import "google/protobuf/wrappers.proto"; + +// Top-level test cases proto used by MarshallingTest. See description +// at the top of the class MarshallingTest for details on how to write +// test cases. +message WrappersTestCases { + DoubleWrapper double_wrapper = 1; + FloatWrapper float_wrapper = 2; + Int64Wrapper int64_wrapper = 3; + UInt64Wrapper uint64_wrapper = 4; + Int32Wrapper int32_wrapper = 5; + UInt32Wrapper uint32_wrapper = 6; + BoolWrapper bool_wrapper = 7; + StringWrapper string_wrapper = 8; + BytesWrapper bytes_wrapper = 9; + + DoubleWrapper double_wrapper_default = 10; + FloatWrapper float_wrapper_default = 11; + Int64Wrapper int64_wrapper_default = 12; + UInt64Wrapper uint64_wrapper_default = 13; + Int32Wrapper int32_wrapper_default = 14; + UInt32Wrapper uint32_wrapper_default = 15; + BoolWrapper bool_wrapper_default = 16; + StringWrapper string_wrapper_default = 17; + BytesWrapper bytes_wrapper_default = 18; +} + +message DoubleWrapper { + google.protobuf.DoubleValue double = 1; +} + +message FloatWrapper { + google.protobuf.FloatValue float = 1; +} + +message Int64Wrapper { + google.protobuf.Int64Value int64 = 1; +} + +message UInt64Wrapper { + google.protobuf.UInt64Value uint64 = 1; +} + +message Int32Wrapper { + google.protobuf.Int32Value int32 = 1; +} + +message UInt32Wrapper { + google.protobuf.UInt32Value uint32 = 1; +} + +message BoolWrapper { + google.protobuf.BoolValue bool = 1; +} + +message StringWrapper { + google.protobuf.StringValue string = 1; +} + +message BytesWrapper { + google.protobuf.BytesValue bytes = 1; +} + +service WrappersTestService { + rpc Call(WrappersTestCases) returns (WrappersTestCases); +} diff --git a/src/google/protobuf/util/internal/type_info.cc b/src/google/protobuf/util/internal/type_info.cc new file mode 100644 index 00000000..6392e18c --- /dev/null +++ b/src/google/protobuf/util/internal/type_info.cc @@ -0,0 +1,171 @@ +// 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/util/internal/type_info.h> + +#include <map> +#include <set> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/type.pb.h> +#include <google/protobuf/stubs/stringpiece.h> +#include <google/protobuf/stubs/map_util.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/statusor.h> +#include <google/protobuf/util/internal/utility.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +namespace { + +// A TypeInfo that looks up information provided by a TypeResolver. +class TypeInfoForTypeResolver : public TypeInfo { + public: + explicit TypeInfoForTypeResolver(TypeResolver* type_resolver) + : type_resolver_(type_resolver) {} + + virtual ~TypeInfoForTypeResolver() { + DeleteCachedTypes(&cached_types_); + DeleteCachedTypes(&cached_enums_); + } + + virtual util::StatusOr<const google::protobuf::Type*> ResolveTypeUrl( + StringPiece type_url) { + map<StringPiece, StatusOrType>::iterator it = cached_types_.find(type_url); + if (it != cached_types_.end()) { + return it->second; + } + // Stores the string value so it can be referenced using StringPiece in the + // cached_types_ map. + const string& string_type_url = + *string_storage_.insert(type_url.ToString()).first; + google::protobuf::scoped_ptr<google::protobuf::Type> type(new google::protobuf::Type()); + util::Status status = + type_resolver_->ResolveMessageType(string_type_url, type.get()); + StatusOrType result = + status.ok() ? StatusOrType(type.release()) : StatusOrType(status); + cached_types_[string_type_url] = result; + return result; + } + + virtual const google::protobuf::Type* GetType(StringPiece type_url) { + StatusOrType result = ResolveTypeUrl(type_url); + return result.ok() ? result.ValueOrDie() : NULL; + } + + virtual const google::protobuf::Enum* GetEnum(StringPiece type_url) { + map<StringPiece, StatusOrEnum>::iterator it = cached_enums_.find(type_url); + if (it != cached_enums_.end()) { + return it->second.ok() ? it->second.ValueOrDie() : NULL; + } + // Stores the string value so it can be referenced using StringPiece in the + // cached_enums_ map. + const string& string_type_url = + *string_storage_.insert(type_url.ToString()).first; + google::protobuf::scoped_ptr<google::protobuf::Enum> enum_type( + new google::protobuf::Enum()); + util::Status status = + type_resolver_->ResolveEnumType(string_type_url, enum_type.get()); + StatusOrEnum result = + status.ok() ? StatusOrEnum(enum_type.release()) : StatusOrEnum(status); + cached_enums_[string_type_url] = result; + return result.ok() ? result.ValueOrDie() : NULL; + } + + virtual const google::protobuf::Field* FindField( + const google::protobuf::Type* type, StringPiece camel_case_name) { + if (indexed_types_.find(type) == indexed_types_.end()) { + PopulateNameLookupTable(type); + indexed_types_.insert(type); + } + StringPiece name = + FindWithDefault(camel_case_name_table_, camel_case_name, StringPiece()); + if (name.empty()) { + // Didn't find a mapping. Use whatever provided. + name = camel_case_name; + } + return FindFieldInTypeOrNull(type, name); + } + + private: + typedef util::StatusOr<const google::protobuf::Type*> StatusOrType; + typedef util::StatusOr<const google::protobuf::Enum*> StatusOrEnum; + + template <typename T> + static void DeleteCachedTypes(map<StringPiece, T>* cached_types) { + for (typename map<StringPiece, T>::iterator it = cached_types->begin(); + it != cached_types->end(); ++it) { + if (it->second.ok()) { + delete it->second.ValueOrDie(); + } + } + } + + void PopulateNameLookupTable(const google::protobuf::Type* type) { + for (int i = 0; i < type->fields_size(); ++i) { + const google::protobuf::Field& field = type->fields(i); + StringPiece name = field.name(); + StringPiece camel_case_name = + *string_storage_.insert(ToCamelCase(name)).first; + const StringPiece* existing = InsertOrReturnExisting( + &camel_case_name_table_, camel_case_name, name); + if (existing && *existing != name) { + GOOGLE_LOG(WARNING) << "Field '" << name << "' and '" << *existing + << "' map to the same camel case name '" << camel_case_name + << "'."; + } + } + } + + TypeResolver* type_resolver_; + + // Stores string values that will be referenced by StringPieces in + // cached_types_, cached_enums_ and camel_case_name_table_. + set<string> string_storage_; + + map<StringPiece, StatusOrType> cached_types_; + map<StringPiece, StatusOrEnum> cached_enums_; + + set<const google::protobuf::Type*> indexed_types_; + map<StringPiece, StringPiece> camel_case_name_table_; +}; +} // namespace + +TypeInfo* TypeInfo::NewTypeInfo(TypeResolver* type_resolver) { + return new TypeInfoForTypeResolver(type_resolver); +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/type_info.h b/src/google/protobuf/util/internal/type_info.h new file mode 100644 index 00000000..67403fff --- /dev/null +++ b/src/google/protobuf/util/internal/type_info.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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_H__ + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/type.pb.h> +#include <google/protobuf/util/type_resolver.h> +#include <google/protobuf/stubs/stringpiece.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/statusor.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { +// Internal helper class for type resolving. Note that this class is not +// thread-safe and should only be accessed in one thread. +class LIBPROTOBUF_EXPORT TypeInfo { + public: + TypeInfo() {} + virtual ~TypeInfo() {} + + // Resolves a type url into a Type. If the type url is invalid, returns + // INVALID_ARGUMENT error status. If the type url is valid but the + // corresponding type cannot be found, returns a NOT_FOUND error status. + // + // This TypeInfo class retains the ownership of the returned pointer. + virtual util::StatusOr<const google::protobuf::Type*> ResolveTypeUrl( + StringPiece type_url) = 0; + + // Resolves a type url into a Type. Like ResolveTypeUrl() but returns + // NULL if the type url is invalid or the type cannot be found. + // + // This TypeInfo class retains the ownership of the returned pointer. + virtual const google::protobuf::Type* GetType(StringPiece type_url) = 0; + + // Resolves a type url for an enum. Returns NULL if the type url is + // invalid or the type cannot be found. + // + // This TypeInfo class retains the ownership of the returned pointer. + virtual const google::protobuf::Enum* GetEnum(StringPiece type_url) = 0; + + // Looks up a field in the specified type given a CamelCase name. + virtual const google::protobuf::Field* FindField( + const google::protobuf::Type* type, StringPiece camel_case_name) = 0; + + static TypeInfo* NewTypeInfo(TypeResolver* type_resolver); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeInfo); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_H__ diff --git a/src/google/protobuf/util/internal/type_info_test_helper.cc b/src/google/protobuf/util/internal/type_info_test_helper.cc new file mode 100644 index 00000000..177b96e2 --- /dev/null +++ b/src/google/protobuf/util/internal/type_info_test_helper.cc @@ -0,0 +1,133 @@ +// 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/util/internal/type_info_test_helper.h> + +#include <memory> +#ifndef _SHARED_PTR_H +#include <google/protobuf/stubs/shared_ptr.h> +#endif +#include <vector> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/util/internal/default_value_objectwriter.h> +#include <google/protobuf/util/internal/type_info.h> +#include <google/protobuf/util/internal/constants.h> +#include <google/protobuf/util/internal/protostream_objectsource.h> +#include <google/protobuf/util/internal/protostream_objectwriter.h> +#include <google/protobuf/util/type_resolver.h> +#include <google/protobuf/util/type_resolver_util.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { +namespace testing { + + +void TypeInfoTestHelper::ResetTypeInfo( + const vector<const Descriptor*>& descriptors) { + switch (type_) { + case USE_TYPE_RESOLVER: { + const DescriptorPool* pool = descriptors[0]->file()->pool(); + for (int i = 1; i < descriptors.size(); ++i) { + GOOGLE_CHECK(pool == descriptors[i]->file()->pool()) + << "Descriptors from different pools are not supported."; + } + type_resolver_.reset( + NewTypeResolverForDescriptorPool(kTypeServiceBaseUrl, pool)); + typeinfo_.reset(TypeInfo::NewTypeInfo(type_resolver_.get())); + return; + } + } + GOOGLE_LOG(FATAL) << "Can not reach here."; +} + +void TypeInfoTestHelper::ResetTypeInfo(const Descriptor* descriptor) { + vector<const Descriptor*> descriptors; + descriptors.push_back(descriptor); + ResetTypeInfo(descriptors); +} + +void TypeInfoTestHelper::ResetTypeInfo(const Descriptor* descriptor1, + const Descriptor* descriptor2) { + vector<const Descriptor*> descriptors; + descriptors.push_back(descriptor1); + descriptors.push_back(descriptor2); + ResetTypeInfo(descriptors); +} + +TypeInfo* TypeInfoTestHelper::GetTypeInfo() { return typeinfo_.get(); } + +ProtoStreamObjectSource* TypeInfoTestHelper::NewProtoSource( + io::CodedInputStream* coded_input, const string& type_url) { + const google::protobuf::Type* type = typeinfo_->GetType(type_url); + switch (type_) { + case USE_TYPE_RESOLVER: { + return new ProtoStreamObjectSource(coded_input, type_resolver_.get(), + *type); + } + } + GOOGLE_LOG(FATAL) << "Can not reach here."; + return NULL; +} + +ProtoStreamObjectWriter* TypeInfoTestHelper::NewProtoWriter( + const string& type_url, strings::ByteSink* output, + ErrorListener* listener) { + const google::protobuf::Type* type = typeinfo_->GetType(type_url); + switch (type_) { + case USE_TYPE_RESOLVER: { + return new ProtoStreamObjectWriter(type_resolver_.get(), *type, output, + listener); + } + } + GOOGLE_LOG(FATAL) << "Can not reach here."; + return NULL; +} + +DefaultValueObjectWriter* TypeInfoTestHelper::NewDefaultValueWriter( + const string& type_url, ObjectWriter* writer) { + const google::protobuf::Type* type = typeinfo_->GetType(type_url); + switch (type_) { + case USE_TYPE_RESOLVER: { + return new DefaultValueObjectWriter(type_resolver_.get(), *type, writer); + } + } + GOOGLE_LOG(FATAL) << "Can not reach here."; + return NULL; +} + +} // namespace testing +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/type_info_test_helper.h b/src/google/protobuf/util/internal/type_info_test_helper.h new file mode 100644 index 00000000..6916a73b --- /dev/null +++ b/src/google/protobuf/util/internal/type_info_test_helper.h @@ -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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_TEST_HELPER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_TEST_HELPER_H__ + +#include <memory> +#ifndef _SHARED_PTR_H +#include <google/protobuf/stubs/shared_ptr.h> +#endif +#include <vector> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/util/internal/type_info.h> +#include <google/protobuf/util/internal/default_value_objectwriter.h> +#include <google/protobuf/util/internal/protostream_objectsource.h> +#include <google/protobuf/util/internal/protostream_objectwriter.h> +#include <google/protobuf/util/type_resolver.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { +namespace testing { + +enum TypeInfoSource { + USE_TYPE_RESOLVER, +}; + +// In the unit-tests we want to test two scenarios: one with type info from +// ServiceTypeInfo, the other with type info from TypeResolver. This class +// wraps the detail of where the type info is from and provides the same +// interface so the same unit-test code can test both scenarios. +class TypeInfoTestHelper { + public: + explicit TypeInfoTestHelper(TypeInfoSource type) : type_(type) {} + + // Creates a TypeInfo object for the given set of descriptors. + void ResetTypeInfo(const vector<const Descriptor*>& descriptors); + + // Convinent overloads. + void ResetTypeInfo(const Descriptor* descriptor); + void ResetTypeInfo(const Descriptor* descriptor1, + const Descriptor* descriptor2); + + // Returns the TypeInfo created after ResetTypeInfo. + TypeInfo* GetTypeInfo(); + + ProtoStreamObjectSource* NewProtoSource(io::CodedInputStream* coded_input, + const string& type_url); + + ProtoStreamObjectWriter* NewProtoWriter(const string& type_url, + strings::ByteSink* output, + ErrorListener* listener); + + DefaultValueObjectWriter* NewDefaultValueWriter(const string& type_url, + ObjectWriter* writer); + + private: + TypeInfoSource type_; + google::protobuf::scoped_ptr<TypeInfo> typeinfo_; + google::protobuf::scoped_ptr<TypeResolver> type_resolver_; +}; +} // namespace testing +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_TEST_HELPER_H__ diff --git a/src/google/protobuf/util/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc new file mode 100644 index 00000000..f550f43b --- /dev/null +++ b/src/google/protobuf/util/internal/utility.cc @@ -0,0 +1,332 @@ +// 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/util/internal/utility.h> + +#include <cmath> +#include <algorithm> +#include <utility> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/wrappers.pb.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/util/internal/constants.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/map_util.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +namespace { +const StringPiece SkipWhiteSpace(StringPiece str) { + StringPiece::size_type i; + for (i = 0; i < str.size() && isspace(str[i]); ++i) {} + GOOGLE_DCHECK(i == str.size() || !isspace(str[i])); + return StringPiece(str, i); +} +} // namespace + +bool GetBoolOptionOrDefault( + const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, + const string& option_name, bool default_value) { + const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); + if (opt == NULL) { + return default_value; + } + return GetBoolFromAny(opt->value()); +} + +int64 GetInt64OptionOrDefault( + const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, + const string& option_name, int64 default_value) { + const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); + if (opt == NULL) { + return default_value; + } + return GetInt64FromAny(opt->value()); +} + +double GetDoubleOptionOrDefault( + const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, + const string& option_name, double default_value) { + const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); + if (opt == NULL) { + return default_value; + } + return GetDoubleFromAny(opt->value()); +} + +string GetStringOptionOrDefault( + const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, + const string& option_name, const string& default_value) { + const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); + if (opt == NULL) { + return default_value; + } + return GetStringFromAny(opt->value()); +} + +template <typename T> +void ParseFromAny(const string& data, T* result) { + result->ParseFromString(data); +} + +// Returns a boolean value contained in Any type. +// TODO(skarvaje): Add type checking & error messages here. +bool GetBoolFromAny(const google::protobuf::Any& any) { + google::protobuf::BoolValue b; + ParseFromAny(any.value(), &b); + return b.value(); +} + +int64 GetInt64FromAny(const google::protobuf::Any& any) { + google::protobuf::Int64Value i; + ParseFromAny(any.value(), &i); + return i.value(); +} + +double GetDoubleFromAny(const google::protobuf::Any& any) { + google::protobuf::DoubleValue i; + ParseFromAny(any.value(), &i); + return i.value(); +} + +string GetStringFromAny(const google::protobuf::Any& any) { + google::protobuf::StringValue s; + ParseFromAny(any.value(), &s); + return s.value(); +} + +const StringPiece GetTypeWithoutUrl(StringPiece type_url) { + size_t idx = type_url.rfind('/'); + return type_url.substr(idx + 1); +} + +const string GetFullTypeWithUrl(StringPiece simple_type) { + return StrCat(kTypeServiceBaseUrl, "/", simple_type); +} + +const google::protobuf::Option* FindOptionOrNull( + const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, + const string& option_name) { + for (int i = 0; i < options.size(); ++i) { + const google::protobuf::Option& opt = options.Get(i); + if (opt.name() == option_name) { + return &opt; + } + } + return NULL; +} + +const google::protobuf::Field* FindFieldInTypeOrNull( + const google::protobuf::Type* type, StringPiece field_name) { + if (type != NULL) { + for (int i = 0; i < type->fields_size(); ++i) { + const google::protobuf::Field& field = type->fields(i); + if (field.name() == field_name) { + return &field; + } + } + } + return NULL; +} + +const google::protobuf::EnumValue* FindEnumValueByNameOrNull( + const google::protobuf::Enum* enum_type, StringPiece enum_name) { + if (enum_type != NULL) { + for (int i = 0; i < enum_type->enumvalue_size(); ++i) { + const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i); + if (enum_value.name() == enum_name) { + return &enum_value; + } + } + } + return NULL; +} + +const google::protobuf::EnumValue* FindEnumValueByNumberOrNull( + const google::protobuf::Enum* enum_type, int32 value) { + if (enum_type != NULL) { + for (int i = 0; i < enum_type->enumvalue_size(); ++i) { + const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i); + if (enum_value.number() == value) { + return &enum_value; + } + } + } + return NULL; +} + +string ToCamelCase(const StringPiece input) { + bool capitalize_next = false; + bool was_cap = true; + bool is_cap = false; + bool first_word = true; + string result; + result.reserve(input.size()); + + for (size_t i = 0; i < input.size(); ++i, was_cap = is_cap) { + is_cap = ascii_isupper(input[i]); + if (input[i] == '_') { + capitalize_next = true; + if (!result.empty()) first_word = false; + continue; + } else if (first_word) { + // Consider when the current character B is capitalized, + // first word ends when: + // 1) following a lowercase: "...aB..." + // 2) followed by a lowercase: "...ABc..." + if (!result.empty() && is_cap && + (!was_cap || (i + 1 < input.size() && ascii_islower(input[i + 1])))) { + first_word = false; + } else { + result.push_back(ascii_tolower(input[i])); + continue; + } + } else if (capitalize_next) { + capitalize_next = false; + if (ascii_islower(input[i])) { + result.push_back(ascii_toupper(input[i])); + continue; + } + } + result.push_back(input[i]); + } + return result; +} + +string ToSnakeCase(StringPiece input) { + bool was_not_underscore = false; // Initialize to false for case 1 (below) + bool was_not_cap = false; + string result; + result.reserve(input.size() << 1); + + for (size_t i = 0; i < input.size(); ++i) { + if (ascii_isupper(input[i])) { + // Consider when the current character B is capitalized: + // 1) At beginning of input: "B..." => "b..." + // (e.g. "Biscuit" => "biscuit") + // 2) Following a lowercase: "...aB..." => "...a_b..." + // (e.g. "gBike" => "g_bike") + // 3) At the end of input: "...AB" => "...ab" + // (e.g. "GoogleLAB" => "google_lab") + // 4) Followed by a lowercase: "...ABc..." => "...a_bc..." + // (e.g. "GBike" => "g_bike") + if (was_not_underscore && // case 1 out + (was_not_cap || // case 2 in, case 3 out + (i + 1 < input.size() && // case 3 out + ascii_islower(input[i + 1])))) { // case 4 in + // We add an underscore for case 2 and case 4. + result.push_back('_'); + } + result.push_back(ascii_tolower(input[i])); + was_not_underscore = true; + was_not_cap = false; + } else { + result.push_back(input[i]); + was_not_underscore = input[i] != '_'; + was_not_cap = true; + } + } + return result; +} + +set<string>* well_known_types_ = NULL; +GOOGLE_PROTOBUF_DECLARE_ONCE(well_known_types_init_); +const char* well_known_types_name_array_[] = { + "google.protobuf.Timestamp", "google.protobuf.Duration", + "google.protobuf.DoubleValue", "google.protobuf.FloatValue", + "google.protobuf.Int64Value", "google.protobuf.UInt64Value", + "google.protobuf.Int32Value", "google.protobuf.UInt32Value", + "google.protobuf.BoolValue", "google.protobuf.StringValue", + "google.protobuf.BytesValue", "google.protobuf.FieldMask"}; + +void DeleteWellKnownTypes() { delete well_known_types_; } + +void InitWellKnownTypes() { + well_known_types_ = new set<string>; + for (int i = 0; i < GOOGLE_ARRAYSIZE(well_known_types_name_array_); ++i) { + well_known_types_->insert(well_known_types_name_array_[i]); + } + google::protobuf::internal::OnShutdown(&DeleteWellKnownTypes); +} + +bool IsWellKnownType(const string& type_name) { + InitWellKnownTypes(); + return ContainsKey(*well_known_types_, type_name); +} + +bool IsValidBoolString(const string& bool_string) { + return bool_string == "true" || bool_string == "false" || + bool_string == "1" || bool_string == "0"; +} + +bool IsMap(const google::protobuf::Field& field, + const google::protobuf::Type& type) { + return (field.cardinality() == + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED && + GetBoolOptionOrDefault(type.options(), + "google.protobuf.MessageOptions.map_entry", false)); +} + +string DoubleAsString(double value) { + if (value == std::numeric_limits<double>::infinity()) return "Infinity"; + if (value == -std::numeric_limits<double>::infinity()) return "-Infinity"; + if (::isnan(value)) return "NaN"; + + return SimpleDtoa(value); +} + +string FloatAsString(float value) { + if (isfinite(value)) return SimpleFtoa(value); + return DoubleAsString(value); +} + +bool SafeStrToFloat(StringPiece str, float *value) { + double double_value; + if (!safe_strtod(str, &double_value)) { + return false; + } + *value = static_cast<float>(double_value); + + if ((*value == numeric_limits<float>::infinity()) || + (*value == -numeric_limits<float>::infinity())) { + return false; + } + return true; +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/utility.h b/src/google/protobuf/util/internal/utility.h new file mode 100644 index 00000000..d0d88c19 --- /dev/null +++ b/src/google/protobuf/util/internal/utility.h @@ -0,0 +1,187 @@ +// 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_UTIL_CONVERTER_UTILITY_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_UTILITY_H__ + +#include <memory> +#ifndef _SHARED_PTR_H +#include <google/protobuf/stubs/shared_ptr.h> +#endif +#include <string> +#include <utility> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/type.pb.h> +#include <google/protobuf/repeated_field.h> +#include <google/protobuf/stubs/stringpiece.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/statusor.h> + + +namespace google { +namespace protobuf { +class Method; +class Any; +class Bool; +class Option; +class Field; +class Type; +class Enum; +class EnumValue; +} // namespace protobuf + + +namespace protobuf { +namespace util { +namespace converter { +// Finds the tech option identified by option_name. Parses the boolean value and +// returns it. +// When the option with the given name is not found, default_value is returned. +LIBPROTOBUF_EXPORT bool GetBoolOptionOrDefault( + const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, + const string& option_name, bool default_value); + +// Returns int64 option value. If the option isn't found, returns the +// default_value. +LIBPROTOBUF_EXPORT int64 GetInt64OptionOrDefault( + const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, + const string& option_name, int64 default_value); + +// Returns double option value. If the option isn't found, returns the +// default_value. +LIBPROTOBUF_EXPORT double GetDoubleOptionOrDefault( + const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, + const string& option_name, double default_value); + +// Returns string option value. If the option isn't found, returns the +// default_value. +LIBPROTOBUF_EXPORT string GetStringOptionOrDefault( + const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, + const string& option_name, const string& default_value); + +// Returns a boolean value contained in Any type. +// TODO(skarvaje): Make these utilities dealing with Any types more generic, +// add more error checking and move to a more public/sharable location so others +// can use. +LIBPROTOBUF_EXPORT bool GetBoolFromAny(const google::protobuf::Any& any); + +// Returns int64 value contained in Any type. +LIBPROTOBUF_EXPORT int64 GetInt64FromAny(const google::protobuf::Any& any); + +// Returns double value contained in Any type. +LIBPROTOBUF_EXPORT double GetDoubleFromAny(const google::protobuf::Any& any); + +// Returns string value contained in Any type. +LIBPROTOBUF_EXPORT string GetStringFromAny(const google::protobuf::Any& any); + +// Returns the type string without the url prefix. e.g.: If the passed type is +// 'type.googleapis.com/tech.type.Bool', the returned value is 'tech.type.Bool'. +LIBPROTOBUF_EXPORT const StringPiece GetTypeWithoutUrl(StringPiece type_url); + +// Returns the simple_type with the base type url (kTypeServiceBaseUrl) +// prefixed. +// +// E.g: +// GetFullTypeWithUrl("google.protobuf.Timestamp") returns the string +// "type.googleapis.com/google.protobuf.Timestamp". +LIBPROTOBUF_EXPORT const string GetFullTypeWithUrl(StringPiece simple_type); + +// Finds and returns option identified by name and option_name within the +// provided map. Returns NULL if none found. +LIBPROTOBUF_EXPORT const google::protobuf::Option* FindOptionOrNull( + const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options, + const string& option_name); + +// Finds and returns the field identified by field_name in the passed tech Type +// object. Returns NULL if none found. +LIBPROTOBUF_EXPORT const google::protobuf::Field* FindFieldInTypeOrNull( + const google::protobuf::Type* type, StringPiece field_name); + +// Finds and returns the EnumValue identified by enum_name in the passed tech +// Enum object. Returns NULL if none found. +LIBPROTOBUF_EXPORT const google::protobuf::EnumValue* FindEnumValueByNameOrNull( + const google::protobuf::Enum* enum_type, StringPiece enum_name); + +// Finds and returns the EnumValue identified by value in the passed tech +// Enum object. Returns NULL if none found. +LIBPROTOBUF_EXPORT const google::protobuf::EnumValue* FindEnumValueByNumberOrNull( + const google::protobuf::Enum* enum_type, int32 value); + +// Converts input to camel-case and returns it. +// Tests are in wrappers/translator/snake2camel_objectwriter_test.cc +// TODO(skarvaje): Isolate tests for this function and put them in +// utility_test.cc +LIBPROTOBUF_EXPORT string ToCamelCase(const StringPiece input); + +// Converts input to snake_case and returns it. +LIBPROTOBUF_EXPORT string ToSnakeCase(StringPiece input); + +// Returns true if type_name represents a well-known type. +LIBPROTOBUF_EXPORT bool IsWellKnownType(const string& type_name); + +// Returns true if 'bool_string' represents a valid boolean value. Only "true", +// "false", "0" and "1" are allowed. +LIBPROTOBUF_EXPORT bool IsValidBoolString(const string& bool_string); + +// Returns true if "field" is a protobuf map field based on its type. +bool IsMap(const google::protobuf::Field& field, + const google::protobuf::Type& type); + +// Infinity/NaN-aware conversion to string. +LIBPROTOBUF_EXPORT string DoubleAsString(double value); +LIBPROTOBUF_EXPORT string FloatAsString(float value); + +// Convert from int32, int64, uint32, uint64, double or float to string. +template <typename T> +string ValueAsString(T value) { + return SimpleItoa(value); +} + +template <> +inline string ValueAsString(float value) { + return FloatAsString(value); +} + +template <> +inline string ValueAsString(double value) { + return DoubleAsString(value); +} + +// Converts a string to float. Unlike safe_strtof, conversion will fail if the +// value fits into double but not float (e.g., DBL_MAX). +LIBPROTOBUF_EXPORT bool SafeStrToFloat(StringPiece str, float* value); +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_UTILITY_H__ diff --git a/src/google/protobuf/util/json_format_proto3.proto b/src/google/protobuf/util/json_format_proto3.proto new file mode 100644 index 00000000..7a282868 --- /dev/null +++ b/src/google/protobuf/util/json_format_proto3.proto @@ -0,0 +1,157 @@ +// 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 proto3; + + +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; +import "google/protobuf/struct.proto"; +import "google/protobuf/any.proto"; +import "google/protobuf/field_mask.proto"; + +enum EnumType { + FOO = 0; + BAR = 1; +} + +message MessageType { + int32 value = 1; +} + +message TestMessage { + bool bool_value = 1; + int32 int32_value = 2; + int64 int64_value = 3; + uint32 uint32_value = 4; + uint64 uint64_value = 5; + float float_value = 6; + double double_value = 7; + string string_value = 8; + bytes bytes_value = 9; + EnumType enum_value = 10; + MessageType message_value = 11; + + repeated bool repeated_bool_value = 21; + repeated int32 repeated_int32_value = 22; + repeated int64 repeated_int64_value = 23; + repeated uint32 repeated_uint32_value = 24; + repeated uint64 repeated_uint64_value = 25; + repeated float repeated_float_value = 26; + repeated double repeated_double_value = 27; + repeated string repeated_string_value = 28; + repeated bytes repeated_bytes_value = 29; + repeated EnumType repeated_enum_value = 30; + repeated MessageType repeated_message_value = 31; +} + +message TestOneof { + // In JSON format oneof fields behave mostly the same as optional + // fields except that: + // 1. Oneof fields have field presence information and will be + // printed if it's set no matter whether it's the default value. + // 2. Multiple oneof fields in the same oneof cannot appear at the + // same time in the input. + oneof oneof_value { + int32 oneof_int32_value = 1; + string oneof_string_value = 2; + bytes oneof_bytes_value = 3; + EnumType oneof_enum_value = 4; + MessageType oneof_message_value = 5; + } +} + +message TestMap { + map<bool, int32> bool_map = 1; + map<int32, int32> int32_map = 2; + map<int64, int32> int64_map = 3; + map<uint32, int32> uint32_map = 4; + map<uint64, int32> uint64_map = 5; + map<string, int32> string_map = 6; +} + +message TestWrapper { + google.protobuf.BoolValue bool_value = 1; + google.protobuf.Int32Value int32_value = 2; + google.protobuf.Int64Value int64_value = 3; + google.protobuf.UInt32Value uint32_value = 4; + google.protobuf.UInt64Value uint64_value = 5; + google.protobuf.FloatValue float_value = 6; + google.protobuf.DoubleValue double_value = 7; + google.protobuf.StringValue string_value = 8; + google.protobuf.BytesValue bytes_value = 9; + + repeated google.protobuf.BoolValue repeated_bool_value = 11; + repeated google.protobuf.Int32Value repeated_int32_value = 12; + repeated google.protobuf.Int64Value repeated_int64_value = 13; + repeated google.protobuf.UInt32Value repeated_uint32_value = 14; + repeated google.protobuf.UInt64Value repeated_uint64_value = 15; + repeated google.protobuf.FloatValue repeated_float_value = 16; + repeated google.protobuf.DoubleValue repeated_double_value = 17; + repeated google.protobuf.StringValue repeated_string_value = 18; + repeated google.protobuf.BytesValue repeated_bytes_value = 19; +} + +message TestTimestamp { + google.protobuf.Timestamp value = 1; + repeated google.protobuf.Timestamp repeated_value = 2; +} + +message TestDuration { + google.protobuf.Duration value = 1; + repeated google.protobuf.Duration repeated_value = 2; +} + +message TestFieldMask { + google.protobuf.FieldMask value = 1; +} + +message TestStruct { + google.protobuf.Struct value = 1; + repeated google.protobuf.Struct repeated_value = 2; +} + +message TestAny { + google.protobuf.Any value = 1; + repeated google.protobuf.Any repeated_value = 2; +} + +message TestValue { + google.protobuf.Value value = 1; + repeated google.protobuf.Value repeated_value = 2; +} + +message TestListValue { + google.protobuf.ListValue value = 1; + repeated google.protobuf.ListValue repeated_value = 2; +} diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc new file mode 100644 index 00000000..6cd40fd5 --- /dev/null +++ b/src/google/protobuf/util/json_util.cc @@ -0,0 +1,142 @@ +// 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/util/json_util.h> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/util/internal/default_value_objectwriter.h> +#include <google/protobuf/util/internal/snake2camel_objectwriter.h> +#include <google/protobuf/util/internal/error_listener.h> +#include <google/protobuf/util/internal/json_objectwriter.h> +#include <google/protobuf/util/internal/json_stream_parser.h> +#include <google/protobuf/util/internal/protostream_objectsource.h> +#include <google/protobuf/util/internal/protostream_objectwriter.h> +#include <google/protobuf/util/type_resolver.h> +#include <google/protobuf/util/type_resolver_util.h> +#include <google/protobuf/stubs/bytestream.h> +#include <google/protobuf/stubs/status_macros.h> + +namespace google { +namespace protobuf { +namespace util { + +namespace internal { +void ZeroCopyStreamByteSink::Append(const char* bytes, size_t len) { + while (len > 0) { + void* buffer; + int length; + if (!stream_->Next(&buffer, &length)) { + // There isn't a way for ByteSink to report errors. + return; + } + if (len < length) { + memcpy(buffer, bytes, len); + stream_->BackUp(length - len); + break; + } else { + memcpy(buffer, bytes, length); + bytes += length; + len -= length; + } + } +} +} // namespace internal + +util::Status BinaryToJsonStream(TypeResolver* resolver, + const string& type_url, + io::ZeroCopyInputStream* binary_input, + io::ZeroCopyOutputStream* json_output, + const JsonOptions& options) { + io::CodedInputStream in_stream(binary_input); + google::protobuf::Type type; + RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type)); + converter::ProtoStreamObjectSource proto_source(&in_stream, resolver, type); + io::CodedOutputStream out_stream(json_output); + converter::JsonObjectWriter json_writer(options.add_whitespace ? " " : "", + &out_stream); + converter::Snake2CamelObjectWriter snake2camel_writer(&json_writer); + if (options.always_print_primitive_fields) { + converter::DefaultValueObjectWriter default_value_writer( + resolver, type, &snake2camel_writer); + return proto_source.WriteTo(&default_value_writer); + } else { + return proto_source.WriteTo(&snake2camel_writer); + } +} + +util::Status BinaryToJsonString(TypeResolver* resolver, + const string& type_url, + const string& binary_input, + string* json_output, + const JsonOptions& options) { + io::ArrayInputStream input_stream(binary_input.data(), binary_input.size()); + io::StringOutputStream output_stream(json_output); + return BinaryToJsonStream(resolver, type_url, &input_stream, &output_stream, + options); +} + +util::Status JsonToBinaryStream(TypeResolver* resolver, + const string& type_url, + io::ZeroCopyInputStream* json_input, + io::ZeroCopyOutputStream* binary_output) { + google::protobuf::Type type; + RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type)); + internal::ZeroCopyStreamByteSink sink(binary_output); + converter::NoopErrorListener listener; + converter::ProtoStreamObjectWriter proto_writer(resolver, type, &sink, + &listener); + + converter::JsonStreamParser parser(&proto_writer); + const void* buffer; + int length; + while (json_input->Next(&buffer, &length)) { + if (length == 0) continue; + RETURN_IF_ERROR( + parser.Parse(StringPiece(static_cast<const char*>(buffer), length))); + } + RETURN_IF_ERROR(parser.FinishParse()); + + return util::Status::OK; +} + +util::Status JsonToBinaryString(TypeResolver* resolver, + const string& type_url, + const string& json_input, + string* binary_output) { + io::ArrayInputStream input_stream(json_input.data(), json_input.size()); + io::StringOutputStream output_stream(binary_output); + return JsonToBinaryStream(resolver, type_url, &input_stream, &output_stream); +} + +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/json_util.h b/src/google/protobuf/util/json_util.h new file mode 100644 index 00000000..6796ea08 --- /dev/null +++ b/src/google/protobuf/util/json_util.h @@ -0,0 +1,136 @@ +// 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. + +// Utility functions to convert between protobuf binary format and proto3 JSON +// format. +#ifndef GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__ +#define GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__ + +#include <google/protobuf/util/type_resolver.h> +#include <google/protobuf/stubs/bytestream.h> + +namespace google { +namespace protobuf { +namespace io { +class ZeroCopyInputStream; +class ZeroCopyOutputStream; +} // namespace io +namespace util { + +struct LIBPROTOBUF_EXPORT JsonOptions { + // Whether to add spaces, line breaks and indentation to make the JSON output + // easy to read. + bool add_whitespace; + // Whether to always print primitive fields. By default primitive fields with + // default values will be omitted in JSON joutput. For example, an int32 field + // set to 0 will be omitted. Set this flag to true will override the default + // behavior and print primitive fields regardless of their values. + bool always_print_primitive_fields; + + JsonOptions() : add_whitespace(false), + always_print_primitive_fields(false) { + } +}; + +// Converts protobuf binary data to JSON. +// The conversion will fail if: +// 1. TypeResolver fails to resolve a type. +// 2. input is not valid protobuf wire format, or conflicts with the type +// information returned by TypeResolver. +// Note that unknown fields will be discarded silently. +LIBPROTOBUF_EXPORT util::Status BinaryToJsonStream( + TypeResolver* resolver, + const string& type_url, + io::ZeroCopyInputStream* binary_input, + io::ZeroCopyOutputStream* json_output, + const JsonOptions& options); + +inline util::Status BinaryToJsonStream( + TypeResolver* resolver, const string& type_url, + io::ZeroCopyInputStream* binary_input, + io::ZeroCopyOutputStream* json_output) { + return BinaryToJsonStream(resolver, type_url, binary_input, json_output, + JsonOptions()); +} + +LIBPROTOBUF_EXPORT util::Status BinaryToJsonString( + TypeResolver* resolver, + const string& type_url, + const string& binary_input, + string* json_output, + const JsonOptions& options); + +inline util::Status BinaryToJsonString(TypeResolver* resolver, + const string& type_url, + const string& binary_input, + string* json_output) { + return BinaryToJsonString(resolver, type_url, binary_input, json_output, + JsonOptions()); +} + +// Converts JSON data to protobuf binary format. +// The conversion will fail if: +// 1. TypeResolver fails to resolve a type. +// 2. input is not valid JSON format, or conflicts with the type +// information returned by TypeResolver. +// 3. input has unknown fields. +LIBPROTOBUF_EXPORT util::Status JsonToBinaryStream( + TypeResolver* resolver, + const string& type_url, + io::ZeroCopyInputStream* json_input, + io::ZeroCopyOutputStream* binary_output); + +LIBPROTOBUF_EXPORT util::Status JsonToBinaryString( + TypeResolver* resolver, + const string& type_url, + const string& json_input, + string* binary_output); + +namespace internal { +// Internal helper class. Put in the header so we can write unit-tests for it. +class LIBPROTOBUF_EXPORT ZeroCopyStreamByteSink : public strings::ByteSink { + public: + explicit ZeroCopyStreamByteSink(io::ZeroCopyOutputStream* stream) + : stream_(stream) {} + + virtual void Append(const char* bytes, size_t len); + + private: + io::ZeroCopyOutputStream* stream_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyStreamByteSink); +}; +} // namespace internal + +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__ diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc new file mode 100644 index 00000000..8399b408 --- /dev/null +++ b/src/google/protobuf/util/json_util_test.cc @@ -0,0 +1,277 @@ +// 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/util/json_util.h> + +#include <list> +#include <string> + +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/util/json_format_proto3.pb.h> +#include <google/protobuf/util/type_resolver.h> +#include <google/protobuf/util/type_resolver_util.h> +#include <gtest/gtest.h> + +namespace google { +namespace protobuf { +namespace util { +namespace { + +using proto3::FOO; +using proto3::BAR; +using proto3::TestMessage; + +static const char kTypeUrlPrefix[] = "type.googleapis.com"; + +static string GetTypeUrl(const Descriptor* message) { + return string(kTypeUrlPrefix) + "/" + message->full_name(); +} + +// As functions defined in json_util.h are just thin wrappers around the +// JSON conversion code in //net/proto2/util/converter, in this test we +// only cover some very basic cases to make sure the wrappers have forwarded +// parameters to the underlying implementation correctly. More detailed +// tests are contained in the //net/proto2/util/converter directory. +class JsonUtilTest : public testing::Test { + protected: + JsonUtilTest() { + resolver_.reset(NewTypeResolverForDescriptorPool( + kTypeUrlPrefix, DescriptorPool::generated_pool())); + } + + string ToJson(const Message& message, const JsonOptions& options) { + string result; + GOOGLE_CHECK_OK(BinaryToJsonString(resolver_.get(), + GetTypeUrl(message.GetDescriptor()), + message.SerializeAsString(), &result, options)); + return result; + } + + bool FromJson(const string& json, Message* message) { + string binary; + GOOGLE_CHECK_OK(JsonToBinaryString( + resolver_.get(), GetTypeUrl(message->GetDescriptor()), json, &binary)); + return message->ParseFromString(binary); + } + + google::protobuf::scoped_ptr<TypeResolver> resolver_; +}; + +TEST_F(JsonUtilTest, TestWhitespaces) { + TestMessage m; + m.mutable_message_value(); + + JsonOptions options; + EXPECT_EQ("{\"messageValue\":{}}", ToJson(m, options)); + options.add_whitespace = true; + EXPECT_EQ( + "{\n" + " \"messageValue\": {}\n" + "}\n", + ToJson(m, options)); +} + +TEST_F(JsonUtilTest, TestDefaultValues) { + TestMessage m; + JsonOptions options; + EXPECT_EQ("{}", ToJson(m, options)); + options.always_print_primitive_fields = true; + EXPECT_EQ( + "{\"boolValue\":false," + "\"int32Value\":0," + "\"int64Value\":\"0\"," + "\"uint32Value\":0," + "\"uint64Value\":\"0\"," + "\"floatValue\":0," + "\"doubleValue\":0," + "\"stringValue\":\"\"," + "\"bytesValue\":\"\"," + // TODO(xiaofeng): The default enum value should be FOO. I believe + // this is a bug in DefaultValueObjectWriter. + "\"enumValue\":null" + "}", + ToJson(m, options)); +} + +TEST_F(JsonUtilTest, ParseMessage) { + // Some random message but good enough to verify that the parsing warpper + // functions are working properly. + string input = + "{\n" + " \"int32Value\": 1024,\n" + " \"repeatedInt32Value\": [1, 2],\n" + " \"messageValue\": {\n" + " \"value\": 2048\n" + " },\n" + " \"repeatedMessageValue\": [\n" + " {\"value\": 40}, {\"value\": 96}\n" + " ]\n" + "}\n"; + TestMessage m; + ASSERT_TRUE(FromJson(input, &m)); + EXPECT_EQ(1024, m.int32_value()); + ASSERT_EQ(2, m.repeated_int32_value_size()); + EXPECT_EQ(1, m.repeated_int32_value(0)); + EXPECT_EQ(2, m.repeated_int32_value(1)); + EXPECT_EQ(2048, m.message_value().value()); + ASSERT_EQ(2, m.repeated_message_value_size()); + EXPECT_EQ(40, m.repeated_message_value(0).value()); + EXPECT_EQ(96, m.repeated_message_value(1).value()); +} + +typedef pair<char*, int> Segment; +// A ZeroCopyOutputStream that writes to multiple buffers. +class SegmentedZeroCopyOutputStream : public io::ZeroCopyOutputStream { + public: + explicit SegmentedZeroCopyOutputStream(list<Segment> segments) + : segments_(segments), last_segment_(NULL, 0), byte_count_(0) {} + + virtual bool Next(void** buffer, int* length) { + if (segments_.empty()) { + return false; + } + last_segment_ = segments_.front(); + segments_.pop_front(); + *buffer = last_segment_.first; + *length = last_segment_.second; + byte_count_ += *length; + return true; + } + + virtual void BackUp(int length) { + GOOGLE_CHECK(length <= last_segment_.second); + segments_.push_front( + Segment(last_segment_.first + last_segment_.second - length, length)); + last_segment_ = Segment(last_segment_.first, last_segment_.second - length); + byte_count_ -= length; + } + + virtual int64 ByteCount() const { return byte_count_; } + + private: + list<Segment> segments_; + Segment last_segment_; + int64 byte_count_; +}; + +// This test splits the output buffer and also the input data into multiple +// segments and checks that the implementation of ZeroCopyStreamByteSink +// handles all possible cases correctly. +TEST(ZeroCopyStreamByteSinkTest, TestAllInputOutputPatterns) { + static const int kOutputBufferLength = 10; + // An exhaustive test takes too long, skip some combinations to make the test + // run faster. + static const int kSkippedPatternCount = 7; + + char buffer[kOutputBufferLength]; + for (int split_pattern = 0; split_pattern < (1 << (kOutputBufferLength - 1)); + split_pattern += kSkippedPatternCount) { + // Split the buffer into small segments according to the split_pattern. + list<Segment> segments; + int segment_start = 0; + for (int i = 0; i < kOutputBufferLength - 1; ++i) { + if (split_pattern & (1 << i)) { + segments.push_back( + Segment(buffer + segment_start, i - segment_start + 1)); + segment_start = i + 1; + } + } + segments.push_back( + Segment(buffer + segment_start, kOutputBufferLength - segment_start)); + + // Write exactly 10 bytes through the ByteSink. + string input_data = "0123456789"; + for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1)); + input_pattern += kSkippedPatternCount) { + memset(buffer, 0, sizeof(buffer)); + { + SegmentedZeroCopyOutputStream output_stream(segments); + internal::ZeroCopyStreamByteSink byte_sink(&output_stream); + int start = 0; + for (int j = 0; j < input_data.length() - 1; ++j) { + if (input_pattern & (1 << j)) { + byte_sink.Append(&input_data[start], j - start + 1); + start = j + 1; + } + } + byte_sink.Append(&input_data[start], input_data.length() - start); + } + EXPECT_EQ(input_data, string(buffer, input_data.length())); + } + + // Write only 9 bytes through the ByteSink. + input_data = "012345678"; + for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1)); + input_pattern += kSkippedPatternCount) { + memset(buffer, 0, sizeof(buffer)); + { + SegmentedZeroCopyOutputStream output_stream(segments); + internal::ZeroCopyStreamByteSink byte_sink(&output_stream); + int start = 0; + for (int j = 0; j < input_data.length() - 1; ++j) { + if (input_pattern & (1 << j)) { + byte_sink.Append(&input_data[start], j - start + 1); + start = j + 1; + } + } + byte_sink.Append(&input_data[start], input_data.length() - start); + } + EXPECT_EQ(input_data, string(buffer, input_data.length())); + EXPECT_EQ(0, buffer[input_data.length()]); + } + + // Write 11 bytes through the ByteSink. The extra byte will just + // be ignored. + input_data = "0123456789A"; + for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1)); + input_pattern += kSkippedPatternCount) { + memset(buffer, 0, sizeof(buffer)); + { + SegmentedZeroCopyOutputStream output_stream(segments); + internal::ZeroCopyStreamByteSink byte_sink(&output_stream); + int start = 0; + for (int j = 0; j < input_data.length() - 1; ++j) { + if (input_pattern & (1 << j)) { + byte_sink.Append(&input_data[start], j - start + 1); + start = j + 1; + } + } + byte_sink.Append(&input_data[start], input_data.length() - start); + } + EXPECT_EQ(input_data.substr(0, kOutputBufferLength), + string(buffer, kOutputBufferLength)); + } + } +} + +} // namespace +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc new file mode 100644 index 00000000..057b414a --- /dev/null +++ b/src/google/protobuf/util/message_differencer.cc @@ -0,0 +1,1629 @@ +// 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. + +// Author: jschorr@google.com (Joseph Schorr) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file defines static methods and classes for comparing Protocol +// Messages (see //google/protobuf/util/message_differencer.h for more +// information). + +#include <google/protobuf/util/message_differencer.h> + +#include <algorithm> +#include <memory> +#ifndef _SHARED_PTR_H +#include <google/protobuf/stubs/shared_ptr.h> +#endif +#include <utility> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/stringprintf.h> +#include <google/protobuf/any.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/dynamic_message.h> +#include <google/protobuf/text_format.h> +#include <google/protobuf/util/field_comparator.h> +#include <google/protobuf/stubs/strutil.h> + +namespace google { +namespace protobuf { + +namespace util { + +// When comparing a repeated field as map, MultipleFieldMapKeyComparator can +// be used to specify multiple fields as key for key comparison. +// Two elements of a repeated field will be regarded as having the same key +// iff they have the same value for every specified key field. +// Note that you can also specify only one field as key. +class MessageDifferencer::MultipleFieldsMapKeyComparator + : public MessageDifferencer::MapKeyComparator { + public: + MultipleFieldsMapKeyComparator( + MessageDifferencer* message_differencer, + const vector<vector<const FieldDescriptor*> >& key_field_paths) + : message_differencer_(message_differencer), + key_field_paths_(key_field_paths) { + GOOGLE_CHECK(!key_field_paths_.empty()); + for (int i = 0; i < key_field_paths_.size(); ++i) { + GOOGLE_CHECK(!key_field_paths_[i].empty()); + } + } + MultipleFieldsMapKeyComparator( + MessageDifferencer* message_differencer, + const FieldDescriptor* key) + : message_differencer_(message_differencer) { + vector<const FieldDescriptor*> key_field_path; + key_field_path.push_back(key); + key_field_paths_.push_back(key_field_path); + } + virtual bool IsMatch( + const Message& message1, + const Message& message2, + const vector<SpecificField>& parent_fields) const { + for (int i = 0; i < key_field_paths_.size(); ++i) { + if (!IsMatchInternal(message1, message2, parent_fields, + key_field_paths_[i], 0)) { + return false; + } + } + return true; + } + private: + bool IsMatchInternal( + const Message& message1, + const Message& message2, + const vector<SpecificField>& parent_fields, + const vector<const FieldDescriptor*>& key_field_path, + int path_index) const { + const FieldDescriptor* field = key_field_path[path_index]; + vector<SpecificField> current_parent_fields(parent_fields); + if (path_index == key_field_path.size() - 1) { + if (field->is_repeated()) { + if (!message_differencer_->CompareRepeatedField( + message1, message2, field, ¤t_parent_fields)) { + return false; + } + } else { + if (!message_differencer_->CompareFieldValueUsingParentFields( + message1, message2, field, -1, -1, ¤t_parent_fields)) { + return false; + } + } + return true; + } else { + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + bool has_field1 = reflection1->HasField(message1, field); + bool has_field2 = reflection2->HasField(message2, field); + if (!has_field1 && !has_field2) { + return true; + } + if (has_field1 != has_field2) { + return false; + } + SpecificField specific_field; + specific_field.field = field; + current_parent_fields.push_back(specific_field); + return IsMatchInternal( + reflection1->GetMessage(message1, field), + reflection2->GetMessage(message2, field), + current_parent_fields, + key_field_path, + path_index + 1); + } + } + MessageDifferencer* message_differencer_; + vector<vector<const FieldDescriptor*> > key_field_paths_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultipleFieldsMapKeyComparator); +}; + +bool MessageDifferencer::Equals(const Message& message1, + const Message& message2) { + MessageDifferencer differencer; + + return differencer.Compare(message1, message2); +} + +bool MessageDifferencer::Equivalent(const Message& message1, + const Message& message2) { + MessageDifferencer differencer; + differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT); + + return differencer.Compare(message1, message2); +} + +bool MessageDifferencer::ApproximatelyEquals(const Message& message1, + const Message& message2) { + MessageDifferencer differencer; + differencer.set_float_comparison( + MessageDifferencer::APPROXIMATE); + + return differencer.Compare(message1, message2); +} + +bool MessageDifferencer::ApproximatelyEquivalent(const Message& message1, + const Message& message2) { + MessageDifferencer differencer; + differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT); + differencer.set_float_comparison(MessageDifferencer::APPROXIMATE); + + return differencer.Compare(message1, message2); +} + +// =========================================================================== + +MessageDifferencer::MessageDifferencer() + : reporter_(NULL), + field_comparator_(NULL), + message_field_comparison_(EQUAL), + scope_(FULL), + repeated_field_comparison_(AS_LIST), + report_matches_(false), + output_string_(NULL) { } + +MessageDifferencer::~MessageDifferencer() { + for (int i = 0; i < owned_key_comparators_.size(); ++i) { + delete owned_key_comparators_[i]; + } + for (int i = 0; i < ignore_criteria_.size(); ++i) { + delete ignore_criteria_[i]; + } +} + +void MessageDifferencer::set_field_comparator(FieldComparator* comparator) { + GOOGLE_CHECK(comparator) << "Field comparator can't be NULL."; + field_comparator_ = comparator; +} + +void MessageDifferencer::set_message_field_comparison( + MessageFieldComparison comparison) { + message_field_comparison_ = comparison; +} + +void MessageDifferencer::set_scope(Scope scope) { + scope_ = scope; +} + +MessageDifferencer::Scope MessageDifferencer::scope() { + return scope_; +} + +void MessageDifferencer::set_float_comparison(FloatComparison comparison) { + default_field_comparator_.set_float_comparison( + comparison == EXACT ? + DefaultFieldComparator::EXACT : DefaultFieldComparator::APPROXIMATE); +} + +void MessageDifferencer::set_repeated_field_comparison( + RepeatedFieldComparison comparison) { + repeated_field_comparison_ = comparison; +} + +void MessageDifferencer::TreatAsSet(const FieldDescriptor* field) { + GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: " + << field->full_name(); + const MapKeyComparator* key_comparator = GetMapKeyComparator(field); + GOOGLE_CHECK(key_comparator == NULL) + << "Cannot treat this repeated field as both Map and Set for" + << " comparison. Field name is: " << field->full_name(); + set_fields_.insert(field); +} + +void MessageDifferencer::TreatAsMap(const FieldDescriptor* field, + const FieldDescriptor* key) { + GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: " + << field->full_name(); + GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type()) + << "Field has to be message type. Field name is: " + << field->full_name(); + GOOGLE_CHECK(key->containing_type() == field->message_type()) + << key->full_name() + << " must be a direct subfield within the repeated field " + << field->full_name() << ", not " << key->containing_type()->full_name(); + GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end()) + << "Cannot treat this repeated field as both Map and Set for " + << "comparison."; + MapKeyComparator* key_comparator = + new MultipleFieldsMapKeyComparator(this, key); + owned_key_comparators_.push_back(key_comparator); + map_field_key_comparator_[field] = key_comparator; +} + +void MessageDifferencer::TreatAsMapWithMultipleFieldsAsKey( + const FieldDescriptor* field, + const vector<const FieldDescriptor*>& key_fields) { + vector<vector<const FieldDescriptor*> > key_field_paths; + for (int i = 0; i < key_fields.size(); ++i) { + vector<const FieldDescriptor*> key_field_path; + key_field_path.push_back(key_fields[i]); + key_field_paths.push_back(key_field_path); + } + TreatAsMapWithMultipleFieldPathsAsKey(field, key_field_paths); +} + +void MessageDifferencer::TreatAsMapWithMultipleFieldPathsAsKey( + const FieldDescriptor* field, + const vector<vector<const FieldDescriptor*> >& key_field_paths) { + GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: " + << field->full_name(); + GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type()) + << "Field has to be message type. Field name is: " + << field->full_name(); + for (int i = 0; i < key_field_paths.size(); ++i) { + const vector<const FieldDescriptor*>& key_field_path = key_field_paths[i]; + for (int j = 0; j < key_field_path.size(); ++j) { + const FieldDescriptor* parent_field = + j == 0 ? field : key_field_path[j - 1]; + const FieldDescriptor* child_field = key_field_path[j]; + GOOGLE_CHECK(child_field->containing_type() == parent_field->message_type()) + << child_field->full_name() + << " must be a direct subfield within the field: " + << parent_field->full_name(); + if (j != 0) { + GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, parent_field->cpp_type()) + << parent_field->full_name() << " has to be of type message."; + GOOGLE_CHECK(!parent_field->is_repeated()) + << parent_field->full_name() << " cannot be a repeated field."; + } + } + } + GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end()) + << "Cannot treat this repeated field as both Map and Set for " + << "comparison."; + MapKeyComparator* key_comparator = + new MultipleFieldsMapKeyComparator(this, key_field_paths); + owned_key_comparators_.push_back(key_comparator); + map_field_key_comparator_[field] = key_comparator; +} + +void MessageDifferencer::TreatAsMapUsingKeyComparator( + const FieldDescriptor* field, + const MapKeyComparator* key_comparator) { + GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: " + << field->full_name(); + GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type()) + << "Field has to be message type. Field name is: " + << field->full_name(); + GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end()) + << "Cannot treat this repeated field as both Map and Set for " + << "comparison."; + map_field_key_comparator_[field] = key_comparator; +} + +void MessageDifferencer::AddIgnoreCriteria(IgnoreCriteria* ignore_criteria) { + ignore_criteria_.push_back(ignore_criteria); +} + +void MessageDifferencer::IgnoreField(const FieldDescriptor* field) { + ignored_fields_.insert(field); +} + +void MessageDifferencer::SetFractionAndMargin(const FieldDescriptor* field, + double fraction, double margin) { + default_field_comparator_.SetFractionAndMargin(field, fraction, margin); +} + +void MessageDifferencer::ReportDifferencesToString(string* output) { + GOOGLE_DCHECK(output) << "Specified output string was NULL"; + + output_string_ = output; + output_string_->clear(); +} + +void MessageDifferencer::ReportDifferencesTo(Reporter* reporter) { + // If an output string is set, clear it to prevent + // it superceding the specified reporter. + if (output_string_) { + output_string_ = NULL; + } + + reporter_ = reporter; +} + +bool MessageDifferencer::FieldBefore(const FieldDescriptor* field1, + const FieldDescriptor* field2) { + // Handle sentinel values (i.e. make sure NULLs are always ordered + // at the end of the list). + if (field1 == NULL) { + return false; + } + + if (field2 == NULL) { + return true; + } + + // Always order fields by their tag number + return (field1->number() < field2->number()); +} + +bool MessageDifferencer::Compare(const Message& message1, + const Message& message2) { + vector<SpecificField> parent_fields; + + bool result = false; + + // Setup the internal reporter if need be. + if (output_string_) { + io::StringOutputStream output_stream(output_string_); + StreamReporter reporter(&output_stream); + reporter_ = &reporter; + result = Compare(message1, message2, &parent_fields); + reporter_ = NULL; + } else { + result = Compare(message1, message2, &parent_fields); + } + + return result; +} + +bool MessageDifferencer::CompareWithFields( + const Message& message1, + const Message& message2, + const vector<const FieldDescriptor*>& message1_fields_arg, + const vector<const FieldDescriptor*>& message2_fields_arg) { + if (message1.GetDescriptor() != message2.GetDescriptor()) { + GOOGLE_LOG(DFATAL) << "Comparison between two messages with different " + << "descriptors."; + return false; + } + + vector<SpecificField> parent_fields; + + bool result = false; + + vector<const FieldDescriptor*> message1_fields(message1_fields_arg); + vector<const FieldDescriptor*> message2_fields(message2_fields_arg); + + std::sort(message1_fields.begin(), message1_fields.end(), FieldBefore); + std::sort(message2_fields.begin(), message2_fields.end(), FieldBefore); + // Append NULL sentinel values. + message1_fields.push_back(NULL); + message2_fields.push_back(NULL); + + // Setup the internal reporter if need be. + if (output_string_) { + io::StringOutputStream output_stream(output_string_); + StreamReporter reporter(&output_stream); + reporter_ = &reporter; + result = CompareRequestedFieldsUsingSettings( + message1, message2, message1_fields, message2_fields, &parent_fields); + reporter_ = NULL; + } else { + result = CompareRequestedFieldsUsingSettings( + message1, message2, message1_fields, message2_fields, &parent_fields); + } + + return result; +} + +bool MessageDifferencer::Compare( + const Message& message1, + const Message& message2, + vector<SpecificField>* parent_fields) { + const Descriptor* descriptor1 = message1.GetDescriptor(); + const Descriptor* descriptor2 = message2.GetDescriptor(); + if (descriptor1 != descriptor2) { + GOOGLE_LOG(DFATAL) << "Comparison between two messages with different " + << "descriptors."; + return false; + } + // Expand google.protobuf.Any payload if possible. + if (descriptor1->full_name() == internal::kAnyFullTypeName) { + google::protobuf::scoped_ptr<Message> data1; + google::protobuf::scoped_ptr<Message> data2; + if (UnpackAny(message1, &data1) && UnpackAny(message2, &data2)) { + return Compare(*data1, *data2, parent_fields); + } + } + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + + // Retrieve all the set fields, including extensions. + vector<const FieldDescriptor*> message1_fields; + vector<const FieldDescriptor*> message2_fields; + + reflection1->ListFields(message1, &message1_fields); + reflection2->ListFields(message2, &message2_fields); + + // Add sentinel values to deal with the + // case where the number of the fields in + // each list are different. + message1_fields.push_back(NULL); + message2_fields.push_back(NULL); + + bool unknown_compare_result = true; + // Ignore unknown fields in EQUIVALENT mode + if (message_field_comparison_ != EQUIVALENT) { + const google::protobuf::UnknownFieldSet* unknown_field_set1 = + &reflection1->GetUnknownFields(message1); + const google::protobuf::UnknownFieldSet* unknown_field_set2 = + &reflection2->GetUnknownFields(message2); + if (!CompareUnknownFields(message1, message2, + *unknown_field_set1, *unknown_field_set2, + parent_fields)) { + if (reporter_ == NULL) { + return false; + }; + unknown_compare_result = false; + } + } + + return CompareRequestedFieldsUsingSettings( + message1, message2, + message1_fields, message2_fields, + parent_fields) && unknown_compare_result; +} + +bool MessageDifferencer::CompareRequestedFieldsUsingSettings( + const Message& message1, + const Message& message2, + const vector<const FieldDescriptor*>& message1_fields, + const vector<const FieldDescriptor*>& message2_fields, + vector<SpecificField>* parent_fields) { + if (scope_ == FULL) { + if (message_field_comparison_ == EQUIVALENT) { + // We need to merge the field lists of both messages (i.e. + // we are merely checking for a difference in field values, + // rather than the addition or deletion of fields). + vector<const FieldDescriptor*> fields_union; + CombineFields(message1_fields, FULL, message2_fields, FULL, + &fields_union); + return CompareWithFieldsInternal(message1, message2, fields_union, + fields_union, parent_fields); + } else { + // Simple equality comparison, use the unaltered field lists. + return CompareWithFieldsInternal(message1, message2, message1_fields, + message2_fields, parent_fields); + } + } else { + if (message_field_comparison_ == EQUIVALENT) { + // We use the list of fields for message1 for both messages when + // comparing. This way, extra fields in message2 are ignored, + // and missing fields in message2 use their default value. + return CompareWithFieldsInternal(message1, message2, message1_fields, + message1_fields, parent_fields); + } else { + // We need to consider the full list of fields for message1 + // but only the intersection for message2. This way, any fields + // only present in message2 will be ignored, but any fields only + // present in message1 will be marked as a difference. + vector<const FieldDescriptor*> fields_intersection; + CombineFields(message1_fields, PARTIAL, message2_fields, PARTIAL, + &fields_intersection); + return CompareWithFieldsInternal(message1, message2, message1_fields, + fields_intersection, parent_fields); + } + } +} + +void MessageDifferencer::CombineFields( + const vector<const FieldDescriptor*>& fields1, + Scope fields1_scope, + const vector<const FieldDescriptor*>& fields2, + Scope fields2_scope, + vector<const FieldDescriptor*>* combined_fields) { + + int index1 = 0; + int index2 = 0; + + while (index1 < fields1.size() && index2 < fields2.size()) { + const FieldDescriptor* field1 = fields1[index1]; + const FieldDescriptor* field2 = fields2[index2]; + + if (FieldBefore(field1, field2)) { + if (fields1_scope == FULL) { + combined_fields->push_back(fields1[index1]); + } + ++index1; + } else if (FieldBefore(field2, field1)) { + if (fields2_scope == FULL) { + combined_fields->push_back(fields2[index2]); + } + ++index2; + } else { + combined_fields->push_back(fields1[index1]); + ++index1; + ++index2; + } + } +} + +bool MessageDifferencer::CompareWithFieldsInternal( + const Message& message1, + const Message& message2, + const vector<const FieldDescriptor*>& message1_fields, + const vector<const FieldDescriptor*>& message2_fields, + vector<SpecificField>* parent_fields) { + bool isDifferent = false; + int field_index1 = 0; + int field_index2 = 0; + + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + + while (true) { + const FieldDescriptor* field1 = message1_fields[field_index1]; + const FieldDescriptor* field2 = message2_fields[field_index2]; + + // Once we have reached sentinel values, we are done the comparison. + if (field1 == NULL && field2 == NULL) { + break; + } + + // Check for differences in the field itself. + if (FieldBefore(field1, field2)) { + // Field 1 is not in the field list for message 2. + if (IsIgnored(message1, message2, field1, *parent_fields)) { + // We are ignoring field1. Report the ignore and move on to + // the next field in message1_fields. + if (reporter_ != NULL) { + SpecificField specific_field; + specific_field.field = field1; + + parent_fields->push_back(specific_field); + reporter_->ReportIgnored(message1, message2, *parent_fields); + parent_fields->pop_back(); + } + ++field_index1; + continue; + } + + if (reporter_ != NULL) { + int count = field1->is_repeated() ? + reflection1->FieldSize(message1, field1) : 1; + + for (int i = 0; i < count; ++i) { + SpecificField specific_field; + specific_field.field = field1; + specific_field.index = field1->is_repeated() ? i : -1; + + parent_fields->push_back(specific_field); + reporter_->ReportDeleted(message1, message2, *parent_fields); + parent_fields->pop_back(); + } + + isDifferent = true; + } else { + return false; + } + + ++field_index1; + continue; + } else if (FieldBefore(field2, field1)) { + // Field 2 is not in the field list for message 1. + if (IsIgnored(message1, message2, field2, *parent_fields)) { + // We are ignoring field2. Report the ignore and move on to + // the next field in message2_fields. + if (reporter_ != NULL) { + SpecificField specific_field; + specific_field.field = field2; + + parent_fields->push_back(specific_field); + reporter_->ReportIgnored(message1, message2, *parent_fields); + parent_fields->pop_back(); + } + ++field_index2; + continue; + } + + if (reporter_ != NULL) { + int count = field2->is_repeated() ? + reflection2->FieldSize(message2, field2) : 1; + + for (int i = 0; i < count; ++i) { + SpecificField specific_field; + specific_field.field = field2; + specific_field.index = field2->is_repeated() ? i : -1; + specific_field.new_index = specific_field.index; + + parent_fields->push_back(specific_field); + reporter_->ReportAdded(message1, message2, *parent_fields); + parent_fields->pop_back(); + } + + isDifferent = true; + } else { + return false; + } + + ++field_index2; + continue; + } + + // By this point, field1 and field2 are guarenteed to point to the same + // field, so we can now compare the values. + if (IsIgnored(message1, message2, field1, *parent_fields)) { + // Ignore this field. Report and move on. + if (reporter_ != NULL) { + SpecificField specific_field; + specific_field.field = field1; + + parent_fields->push_back(specific_field); + reporter_->ReportIgnored(message1, message2, *parent_fields); + parent_fields->pop_back(); + } + + ++field_index1; + ++field_index2; + continue; + } + + bool fieldDifferent = false; + if (field1->is_repeated()) { + fieldDifferent = !CompareRepeatedField(message1, message2, field1, + parent_fields); + if (fieldDifferent) { + if (reporter_ == NULL) return false; + isDifferent = true; + } + } else { + fieldDifferent = !CompareFieldValueUsingParentFields( + message1, message2, field1, -1, -1, parent_fields); + + // If we have found differences, either report them or terminate if + // no reporter is present. + if (fieldDifferent && reporter_ == NULL) { + return false; + } + + if (reporter_ != NULL) { + SpecificField specific_field; + specific_field.field = field1; + parent_fields->push_back(specific_field); + if (fieldDifferent) { + reporter_->ReportModified(message1, message2, *parent_fields); + isDifferent = true; + } else if (report_matches_) { + reporter_->ReportMatched(message1, message2, *parent_fields); + } + parent_fields->pop_back(); + } + } + // Increment the field indicies. + ++field_index1; + ++field_index2; + } + + return !isDifferent; +} + +bool MessageDifferencer::IsMatch(const FieldDescriptor* repeated_field, + const MapKeyComparator* key_comparator, + const Message* message1, + const Message* message2, + const vector<SpecificField>& parent_fields, + int index1, int index2) { + vector<SpecificField> current_parent_fields(parent_fields); + if (repeated_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + return CompareFieldValueUsingParentFields( + *message1, *message2, repeated_field, index1, index2, + ¤t_parent_fields); + } + // Back up the Reporter and output_string_. They will be reset in the + // following code. + Reporter* backup_reporter = reporter_; + string* output_string = output_string_; + reporter_ = NULL; + output_string_ = NULL; + bool match; + + if (key_comparator == NULL) { + match = CompareFieldValueUsingParentFields( + *message1, *message2, repeated_field, index1, index2, + ¤t_parent_fields); + } else { + const Reflection* reflection1 = message1->GetReflection(); + const Reflection* reflection2 = message2->GetReflection(); + const Message& m1 = + reflection1->GetRepeatedMessage(*message1, repeated_field, index1); + const Message& m2 = + reflection2->GetRepeatedMessage(*message2, repeated_field, index2); + SpecificField specific_field; + specific_field.field = repeated_field; + current_parent_fields.push_back(specific_field); + match = key_comparator->IsMatch(m1, m2, current_parent_fields); + } + + reporter_ = backup_reporter; + output_string_ = output_string; + return match; +} + +bool MessageDifferencer::CompareRepeatedField( + const Message& message1, + const Message& message2, + const FieldDescriptor* repeated_field, + vector<SpecificField>* parent_fields) { + // the input FieldDescriptor is guaranteed to be repeated field. + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + const int count1 = reflection1->FieldSize(message1, repeated_field); + const int count2 = reflection2->FieldSize(message2, repeated_field); + const bool treated_as_subset = IsTreatedAsSubset(repeated_field); + + // If the field is not treated as subset and no detailed reports is needed, + // we do a quick check on the number of the elements to avoid unnecessary + // comparison. + if (count1 != count2 && reporter_ == NULL && !treated_as_subset) { + return false; + } + // A match can never be found if message1 has more items than message2. + if (count1 > count2 && reporter_ == NULL) { + return false; + } + + // These two list are used for store the index of the correspondent + // element in peer repeated field. + vector<int> match_list1; + vector<int> match_list2; + + // Try to match indices of the repeated fields. Return false if match fails + // and there's no detailed report needed. + if (!MatchRepeatedFieldIndices(message1, message2, repeated_field, + *parent_fields, &match_list1, &match_list2) && + reporter_ == NULL) { + return false; + } + + bool fieldDifferent = false; + SpecificField specific_field; + specific_field.field = repeated_field; + + // At this point, we have already matched pairs of fields (with the reporting + // to be done later). Now to check if the paired elements are different. + for (int i = 0; i < count1; i++) { + if (match_list1[i] == -1) continue; + specific_field.index = i; + specific_field.new_index = match_list1[i]; + + const bool result = CompareFieldValueUsingParentFields( + message1, message2, repeated_field, i, specific_field.new_index, + parent_fields); + + // If we have found differences, either report them or terminate if + // no reporter is present. Note that ReportModified, ReportMoved, and + // ReportMatched are all mutually exclusive. + if (!result) { + if (reporter_ == NULL) return false; + parent_fields->push_back(specific_field); + reporter_->ReportModified(message1, message2, *parent_fields); + parent_fields->pop_back(); + fieldDifferent = true; + } else if (reporter_ != NULL && + specific_field.index != specific_field.new_index) { + parent_fields->push_back(specific_field); + reporter_->ReportMoved(message1, message2, *parent_fields); + parent_fields->pop_back(); + } else if (report_matches_ && reporter_ != NULL) { + parent_fields->push_back(specific_field); + reporter_->ReportMatched(message1, message2, *parent_fields); + parent_fields->pop_back(); + } + } + + // Report any remaining additions or deletions. + for (int i = 0; i < count2; ++i) { + if (match_list2[i] != -1) continue; + if (!treated_as_subset) { + fieldDifferent = true; + } + + if (reporter_ == NULL) continue; + specific_field.index = i; + specific_field.new_index = i; + parent_fields->push_back(specific_field); + reporter_->ReportAdded(message1, message2, *parent_fields); + parent_fields->pop_back(); + } + + for (int i = 0; i < count1; ++i) { + if (match_list1[i] != -1) continue; + specific_field.index = i; + parent_fields->push_back(specific_field); + reporter_->ReportDeleted(message1, message2, *parent_fields); + parent_fields->pop_back(); + fieldDifferent = true; + } + return !fieldDifferent; +} + +bool MessageDifferencer::CompareFieldValue(const Message& message1, + const Message& message2, + const FieldDescriptor* field, + int index1, + int index2) { + return CompareFieldValueUsingParentFields(message1, message2, field, index1, + index2, NULL); +} + +bool MessageDifferencer::CompareFieldValueUsingParentFields( + const Message& message1, const Message& message2, + const FieldDescriptor* field, int index1, int index2, + vector<SpecificField>* parent_fields) { + FieldContext field_context(parent_fields); + FieldComparator::ComparisonResult result = GetFieldComparisonResult( + message1, message2, field, index1, index2, &field_context); + + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + result == FieldComparator::RECURSE) { + // Get the nested messages and compare them using one of the Compare + // methods. + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + const Message& m1 = field->is_repeated() ? + reflection1->GetRepeatedMessage(message1, field, index1) : + reflection1->GetMessage(message1, field); + const Message& m2 = field->is_repeated() ? + reflection2->GetRepeatedMessage(message2, field, index2) : + reflection2->GetMessage(message2, field); + + // parent_fields is used in calls to Reporter methods. + if (parent_fields != NULL) { + // Append currently compared field to the end of parent_fields. + SpecificField specific_field; + specific_field.field = field; + specific_field.index = index1; + specific_field.new_index = index2; + parent_fields->push_back(specific_field); + const bool compare_result = Compare(m1, m2, parent_fields); + parent_fields->pop_back(); + return compare_result; + } else { + // Recreates parent_fields as if m1 and m2 had no parents. + return Compare(m1, m2); + } + } else { + return (result == FieldComparator::SAME); + } +} + +bool MessageDifferencer::CheckPathChanged( + const vector<SpecificField>& field_path) { + for (int i = 0; i < field_path.size(); ++i) { + if (field_path[i].index != field_path[i].new_index) return true; + } + return false; +} + +bool MessageDifferencer::IsTreatedAsSet(const FieldDescriptor* field) { + if (!field->is_repeated()) return false; + if (field->is_map()) return true; + if (repeated_field_comparison_ == AS_SET) return true; + return (set_fields_.find(field) != set_fields_.end()); +} + +bool MessageDifferencer::IsTreatedAsSubset(const FieldDescriptor* field) { + return scope_ == PARTIAL && + (IsTreatedAsSet(field) || GetMapKeyComparator(field) != NULL); +} + +bool MessageDifferencer::IsIgnored( + const Message& message1, + const Message& message2, + const FieldDescriptor* field, + const vector<SpecificField>& parent_fields) { + if (ignored_fields_.find(field) != ignored_fields_.end()) { + return true; + } + for (int i = 0; i < ignore_criteria_.size(); ++i) { + if (ignore_criteria_[i]->IsIgnored(message1, message2, field, + parent_fields)) { + return true; + } + } + return false; +} + +const MessageDifferencer::MapKeyComparator* MessageDifferencer + ::GetMapKeyComparator(const FieldDescriptor* field) { + if (!field->is_repeated()) return NULL; + if (map_field_key_comparator_.find(field) != + map_field_key_comparator_.end()) { + return map_field_key_comparator_[field]; + } + return NULL; +} + +namespace { + +typedef pair<int, const UnknownField*> IndexUnknownFieldPair; + +struct UnknownFieldOrdering { + inline bool operator()(const IndexUnknownFieldPair& a, + const IndexUnknownFieldPair& b) const { + if (a.second->number() < b.second->number()) return true; + if (a.second->number() > b.second->number()) return false; + return a.second->type() < b.second->type(); + } +}; + +} // namespace + +bool MessageDifferencer::UnpackAny(const Message& any, + google::protobuf::scoped_ptr<Message>* data) { + const Reflection* reflection = any.GetReflection(); + const FieldDescriptor* type_url_field; + const FieldDescriptor* value_field; + if (!internal::GetAnyFieldDescriptors(any, &type_url_field, &value_field)) { + return false; + } + const string& type_url = reflection->GetString(any, type_url_field); + string full_type_name; + if (!internal::ParseAnyTypeUrl(type_url, &full_type_name)) { + return false; + } + + const google::protobuf::Descriptor* desc = + any.GetDescriptor()->file()->pool()->FindMessageTypeByName( + full_type_name); + if (desc == NULL) { + GOOGLE_LOG(ERROR) << "Proto type '" << full_type_name << "' not found"; + return false; + } + + if (dynamic_message_factory_ == NULL) { + dynamic_message_factory_.reset(new DynamicMessageFactory()); + } + data->reset(dynamic_message_factory_->GetPrototype(desc)->New()); + string serialized_value = reflection->GetString(any, value_field); + if (!(*data)->ParseFromString(serialized_value)) { + GOOGLE_LOG(ERROR) << "Failed to parse value for " << full_type_name; + return false; + } + return true; +} + +bool MessageDifferencer::CompareUnknownFields( + const Message& message1, const Message& message2, + const google::protobuf::UnknownFieldSet& unknown_field_set1, + const google::protobuf::UnknownFieldSet& unknown_field_set2, + vector<SpecificField>* parent_field) { + // Ignore unknown fields in EQUIVALENT mode. + if (message_field_comparison_ == EQUIVALENT) return true; + + if (unknown_field_set1.empty() && unknown_field_set2.empty()) { + return true; + } + + bool is_different = false; + + // We first sort the unknown fields by field number and type (in other words, + // in tag order), making sure to preserve ordering of values with the same + // tag. This allows us to report only meaningful differences between the + // two sets -- that is, differing values for the same tag. We use + // IndexUnknownFieldPairs to keep track of the field's original index for + // reporting purposes. + vector<IndexUnknownFieldPair> fields1; // unknown_field_set1, sorted + vector<IndexUnknownFieldPair> fields2; // unknown_field_set2, sorted + fields1.reserve(unknown_field_set1.field_count()); + fields2.reserve(unknown_field_set2.field_count()); + + for (int i = 0; i < unknown_field_set1.field_count(); i++) { + fields1.push_back(std::make_pair(i, &unknown_field_set1.field(i))); + } + for (int i = 0; i < unknown_field_set2.field_count(); i++) { + fields2.push_back(std::make_pair(i, &unknown_field_set2.field(i))); + } + + UnknownFieldOrdering is_before; + std::stable_sort(fields1.begin(), fields1.end(), is_before); + std::stable_sort(fields2.begin(), fields2.end(), is_before); + + // In order to fill in SpecificField::index, we have to keep track of how + // many values we've seen with the same field number and type. + // current_repeated points at the first field in this range, and + // current_repeated_start{1,2} are the indexes of the first field in the + // range within fields1 and fields2. + const UnknownField* current_repeated = NULL; + int current_repeated_start1 = 0; + int current_repeated_start2 = 0; + + // Now that we have two sorted lists, we can detect fields which appear only + // in one list or the other by traversing them simultaneously. + int index1 = 0; + int index2 = 0; + while (index1 < fields1.size() || index2 < fields2.size()) { + enum { ADDITION, DELETION, MODIFICATION, COMPARE_GROUPS, + NO_CHANGE } change_type; + + // focus_field is the field we're currently reporting on. (In the case + // of a modification, it's the field on the left side.) + const UnknownField* focus_field; + bool match = false; + + if (index2 == fields2.size() || + (index1 < fields1.size() && + is_before(fields1[index1], fields2[index2]))) { + // fields1[index1] is not present in fields2. + change_type = DELETION; + focus_field = fields1[index1].second; + } else if (index1 == fields1.size() || + is_before(fields2[index2], fields1[index1])) { + // fields2[index2] is not present in fields1. + if (scope_ == PARTIAL) { + // Ignore. + ++index2; + continue; + } + change_type = ADDITION; + focus_field = fields2[index2].second; + } else { + // Field type and number are the same. See if the values differ. + change_type = MODIFICATION; + focus_field = fields1[index1].second; + + switch (focus_field->type()) { + case UnknownField::TYPE_VARINT: + match = fields1[index1].second->varint() == + fields2[index2].second->varint(); + break; + case UnknownField::TYPE_FIXED32: + match = fields1[index1].second->fixed32() == + fields2[index2].second->fixed32(); + break; + case UnknownField::TYPE_FIXED64: + match = fields1[index1].second->fixed64() == + fields2[index2].second->fixed64(); + break; + case UnknownField::TYPE_LENGTH_DELIMITED: + match = fields1[index1].second->length_delimited() == + fields2[index2].second->length_delimited(); + break; + case UnknownField::TYPE_GROUP: + // We must deal with this later, after building the SpecificField. + change_type = COMPARE_GROUPS; + break; + } + if (match && change_type != COMPARE_GROUPS) { + change_type = NO_CHANGE; + } + } + + if (current_repeated == NULL || + focus_field->number() != current_repeated->number() || + focus_field->type() != current_repeated->type()) { + // We've started a new repeated field. + current_repeated = focus_field; + current_repeated_start1 = index1; + current_repeated_start2 = index2; + } + + if (change_type == NO_CHANGE && reporter_ == NULL) { + // Fields were already compared and matched and we have no reporter. + ++index1; + ++index2; + continue; + } + + if (change_type == ADDITION || change_type == DELETION || + change_type == MODIFICATION) { + if (reporter_ == NULL) { + // We found a difference and we have no reproter. + return false; + } + is_different = true; + } + + // Build the SpecificField. This is slightly complicated. + SpecificField specific_field; + specific_field.unknown_field_number = focus_field->number(); + specific_field.unknown_field_type = focus_field->type(); + + specific_field.unknown_field_set1 = &unknown_field_set1; + specific_field.unknown_field_set2 = &unknown_field_set2; + + if (change_type != ADDITION) { + specific_field.unknown_field_index1 = fields1[index1].first; + } + if (change_type != DELETION) { + specific_field.unknown_field_index2 = fields2[index2].first; + } + + // Calculate the field index. + if (change_type == ADDITION) { + specific_field.index = index2 - current_repeated_start2; + specific_field.new_index = index2 - current_repeated_start2; + } else { + specific_field.index = index1 - current_repeated_start1; + specific_field.new_index = index2 - current_repeated_start2; + } + + parent_field->push_back(specific_field); + + switch (change_type) { + case ADDITION: + reporter_->ReportAdded(message1, message2, *parent_field); + ++index2; + break; + case DELETION: + reporter_->ReportDeleted(message1, message2, *parent_field); + ++index1; + break; + case MODIFICATION: + reporter_->ReportModified(message1, message2, *parent_field); + ++index1; + ++index2; + break; + case COMPARE_GROUPS: + if (!CompareUnknownFields(message1, message2, + fields1[index1].second->group(), + fields2[index2].second->group(), + parent_field)) { + if (reporter_ == NULL) return false; + is_different = true; + reporter_->ReportModified(message1, message2, *parent_field); + } + ++index1; + ++index2; + break; + case NO_CHANGE: + ++index1; + ++index2; + if (report_matches_) { + reporter_->ReportMatched(message1, message2, *parent_field); + } + } + + parent_field->pop_back(); + } + + return !is_different; +} + +namespace { + +// Find maximum bipartite matching using the argumenting path algorithm. +class MaximumMatcher { + public: + typedef ResultCallback2<bool, int, int> NodeMatchCallback; + // MaximumMatcher takes ownership of the passed in callback and uses it to + // determine whether a node on the left side of the bipartial graph matches + // a node on the right side. count1 is the number of nodes on the left side + // of the graph and count2 to is the number of nodes on the right side. + // Every node is referred to using 0-based indices. + // If a maximum match is found, the result will be stored in match_list1 and + // match_list2. match_list1[i] == j means the i-th node on the left side is + // matched to the j-th node on the right side and match_list2[x] == y means + // the x-th node on the right side is matched to y-th node on the left side. + // match_list1[i] == -1 means the node is not matched. Same with match_list2. + MaximumMatcher(int count1, int count2, NodeMatchCallback* callback, + vector<int>* match_list1, vector<int>* match_list2); + // Find a maximum match and return the number of matched node pairs. + // If early_return is true, this method will return 0 immediately when it + // finds that not all nodes on the left side can be matched. + int FindMaximumMatch(bool early_return); + private: + // Determines whether the node on the left side of the bipartial graph + // matches the one on the right side. + bool Match(int left, int right); + // Find an argumenting path starting from the node v on the left side. If a + // path can be found, update match_list2_ to reflect the path and return + // true. + bool FindArgumentPathDFS(int v, vector<bool>* visited); + + int count1_; + int count2_; + google::protobuf::scoped_ptr<NodeMatchCallback> match_callback_; + map<pair<int, int>, bool> cached_match_results_; + vector<int>* match_list1_; + vector<int>* match_list2_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MaximumMatcher); +}; + +MaximumMatcher::MaximumMatcher(int count1, int count2, + NodeMatchCallback* callback, + vector<int>* match_list1, + vector<int>* match_list2) + : count1_(count1), count2_(count2), match_callback_(callback), + match_list1_(match_list1), match_list2_(match_list2) { + match_list1_->assign(count1, -1); + match_list2_->assign(count2, -1); +} + +int MaximumMatcher::FindMaximumMatch(bool early_return) { + int result = 0; + for (int i = 0; i < count1_; ++i) { + vector<bool> visited(count1_); + if (FindArgumentPathDFS(i, &visited)) { + ++result; + } else if (early_return) { + return 0; + } + } + // Backfill match_list1_ as we only filled match_list2_ when finding + // argumenting pathes. + for (int i = 0; i < count2_; ++i) { + if ((*match_list2_)[i] != -1) { + (*match_list1_)[(*match_list2_)[i]] = i; + } + } + return result; +} + +bool MaximumMatcher::Match(int left, int right) { + pair<int, int> p(left, right); + map<pair<int, int>, bool>::iterator it = cached_match_results_.find(p); + if (it != cached_match_results_.end()) { + return it->second; + } + cached_match_results_[p] = match_callback_->Run(left, right); + return cached_match_results_[p]; +} + +bool MaximumMatcher::FindArgumentPathDFS(int v, vector<bool>* visited) { + (*visited)[v] = true; + // We try to match those un-matched nodes on the right side first. This is + // the step that the navie greedy matching algorithm uses. In the best cases + // where the greedy algorithm can find a maximum matching, we will always + // find a match in this step and the performance will be identical to the + // greedy algorithm. + for (int i = 0; i < count2_; ++i) { + int matched = (*match_list2_)[i]; + if (matched == -1 && Match(v, i)) { + (*match_list2_)[i] = v; + return true; + } + } + // Then we try those already matched nodes and see if we can find an + // alternaive match for the node matched to them. + // The greedy algorithm will stop before this and fail to produce the + // correct result. + for (int i = 0; i < count2_; ++i) { + int matched = (*match_list2_)[i]; + if (matched != -1 && Match(v, i)) { + if (!(*visited)[matched] && FindArgumentPathDFS(matched, visited)) { + (*match_list2_)[i] = v; + return true; + } + } + } + return false; +} + +} // namespace + +bool MessageDifferencer::MatchRepeatedFieldIndices( + const Message& message1, + const Message& message2, + const FieldDescriptor* repeated_field, + const vector<SpecificField>& parent_fields, + vector<int>* match_list1, + vector<int>* match_list2) { + const int count1 = + message1.GetReflection()->FieldSize(message1, repeated_field); + const int count2 = + message2.GetReflection()->FieldSize(message2, repeated_field); + const MapKeyComparator* key_comparator = GetMapKeyComparator(repeated_field); + + match_list1->assign(count1, -1); + match_list2->assign(count2, -1); + + SpecificField specific_field; + specific_field.field = repeated_field; + + bool success = true; + // Find potential match if this is a special repeated field. + if (key_comparator != NULL || IsTreatedAsSet(repeated_field)) { + if (scope_ == PARTIAL) { + // When partial matching is enabled, Compare(a, b) && Compare(a, c) + // doesn't neccessarily imply Compare(b, c). Therefore a naive greedy + // algorithm will fail to find a maximum matching. + // Here we use the argumenting path algorithm. + MaximumMatcher::NodeMatchCallback* callback = NewPermanentCallback( + this, &MessageDifferencer::IsMatch, repeated_field, key_comparator, + &message1, &message2, parent_fields); + MaximumMatcher matcher(count1, count2, callback, match_list1, + match_list2); + // If diff info is not needed, we should end the matching process as + // soon as possible if not all items can be matched. + bool early_return = (reporter_ == NULL); + int match_count = matcher.FindMaximumMatch(early_return); + if (match_count != count1 && reporter_ == NULL) return false; + success = success && (match_count == count1); + } else { + for (int i = 0; i < count1; ++i) { + // Indicates any matched elements for this repeated field. + bool match = false; + + specific_field.index = i; + specific_field.new_index = i; + + for (int j = 0; j < count2; j++) { + if (match_list2->at(j) != -1) continue; + specific_field.index = i; + specific_field.new_index = j; + + match = IsMatch(repeated_field, key_comparator, + &message1, &message2, parent_fields, i, j); + + if (match) { + match_list1->at(specific_field.index) = specific_field.new_index; + match_list2->at(specific_field.new_index) = specific_field.index; + break; + } + } + if (!match && reporter_ == NULL) return false; + success = success && match; + } + } + } else { + // If this field should be treated as list, just label the match_list. + for (int i = 0; i < count1 && i < count2; i++) { + match_list1->at(i) = i; + match_list2->at(i) = i; + } + } + + return success; +} + +FieldComparator::ComparisonResult MessageDifferencer::GetFieldComparisonResult( + const Message& message1, const Message& message2, + const FieldDescriptor* field, int index1, int index2, + const FieldContext* field_context) { + FieldComparator* comparator = field_comparator_ != NULL ? + field_comparator_ : &default_field_comparator_; + return comparator->Compare(message1, message2, field, + index1, index2, field_context); +} + +// =========================================================================== + +MessageDifferencer::Reporter::Reporter() { } +MessageDifferencer::Reporter::~Reporter() {} + +// =========================================================================== + +MessageDifferencer::MapKeyComparator::MapKeyComparator() {} +MessageDifferencer::MapKeyComparator::~MapKeyComparator() {} + +// =========================================================================== + +MessageDifferencer::IgnoreCriteria::IgnoreCriteria() {} +MessageDifferencer::IgnoreCriteria::~IgnoreCriteria() {} + +// =========================================================================== + +// Note that the printer's delimiter is not used, because if we are given a +// printer, we don't know its delimiter. +MessageDifferencer::StreamReporter::StreamReporter( + io::ZeroCopyOutputStream* output) : printer_(new io::Printer(output, '$')), + delete_printer_(true), + report_modified_aggregates_(false) { } + +MessageDifferencer::StreamReporter::StreamReporter( + io::Printer* printer) : printer_(printer), + delete_printer_(false), + report_modified_aggregates_(false) { } + +MessageDifferencer::StreamReporter::~StreamReporter() { + if (delete_printer_) delete printer_; +} + +void MessageDifferencer::StreamReporter::PrintPath( + const vector<SpecificField>& field_path, bool left_side) { + for (int i = 0; i < field_path.size(); ++i) { + if (i > 0) { + printer_->Print("."); + } + + SpecificField specific_field = field_path[i]; + + if (specific_field.field != NULL) { + if (specific_field.field->is_extension()) { + printer_->Print("($name$)", "name", + specific_field.field->full_name()); + } else { + printer_->PrintRaw(specific_field.field->name()); + } + } else { + printer_->PrintRaw(SimpleItoa(specific_field.unknown_field_number)); + } + if (left_side && specific_field.index >= 0) { + printer_->Print("[$name$]", "name", SimpleItoa(specific_field.index)); + } + if (!left_side && specific_field.new_index >= 0) { + printer_->Print("[$name$]", "name", SimpleItoa(specific_field.new_index)); + } + } +} + +void MessageDifferencer:: +StreamReporter::PrintValue(const Message& message, + const vector<SpecificField>& field_path, + bool left_side) { + const SpecificField& specific_field = field_path.back(); + const FieldDescriptor* field = specific_field.field; + if (field != NULL) { + string output; + int index = left_side ? specific_field.index : specific_field.new_index; + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + const Reflection* reflection = message.GetReflection(); + const Message& field_message = field->is_repeated() ? + reflection->GetRepeatedMessage(message, field, index) : + reflection->GetMessage(message, field); + output = field_message.ShortDebugString(); + if (output.empty()) { + printer_->Print("{ }"); + } else { + printer_->Print("{ $name$ }", "name", output); + } + } else { + TextFormat::PrintFieldValueToString(message, field, index, &output); + printer_->PrintRaw(output); + } + } else { + const UnknownFieldSet* unknown_fields = + (left_side ? + specific_field.unknown_field_set1 : + specific_field.unknown_field_set2); + const UnknownField* unknown_field = &unknown_fields->field( + left_side ? + specific_field.unknown_field_index1 : + specific_field.unknown_field_index2); + PrintUnknownFieldValue(unknown_field); + } +} + +void MessageDifferencer:: +StreamReporter::PrintUnknownFieldValue(const UnknownField* unknown_field) { + GOOGLE_CHECK(unknown_field != NULL) << " Cannot print NULL unknown_field."; + + string output; + switch (unknown_field->type()) { + case UnknownField::TYPE_VARINT: + output = SimpleItoa(unknown_field->varint()); + break; + case UnknownField::TYPE_FIXED32: + output = StrCat("0x", strings::Hex(unknown_field->fixed32(), + strings::ZERO_PAD_8)); + break; + case UnknownField::TYPE_FIXED64: + output = StrCat("0x", strings::Hex(unknown_field->fixed64(), + strings::ZERO_PAD_16)); + break; + case UnknownField::TYPE_LENGTH_DELIMITED: + output = StringPrintf("\"%s\"", + CEscape(unknown_field->length_delimited()).c_str()); + break; + case UnknownField::TYPE_GROUP: + // TODO(kenton): Print the contents of the group like we do for + // messages. Requires an equivalent of ShortDebugString() for + // UnknownFieldSet. + output = "{ ... }"; + break; + } + printer_->PrintRaw(output); +} + +void MessageDifferencer::StreamReporter::Print(const string& str) { + printer_->Print(str.c_str()); +} + +void MessageDifferencer::StreamReporter::ReportAdded( + const Message& message1, + const Message& message2, + const vector<SpecificField>& field_path) { + printer_->Print("added: "); + PrintPath(field_path, false); + printer_->Print(": "); + PrintValue(message2, field_path, false); + printer_->Print("\n"); // Print for newlines. +} + +void MessageDifferencer::StreamReporter::ReportDeleted( + const Message& message1, + const Message& message2, + const vector<SpecificField>& field_path) { + printer_->Print("deleted: "); + PrintPath(field_path, true); + printer_->Print(": "); + PrintValue(message1, field_path, true); + printer_->Print("\n"); // Print for newlines +} + +void MessageDifferencer::StreamReporter::ReportModified( + const Message& message1, + const Message& message2, + const vector<SpecificField>& field_path) { + if (!report_modified_aggregates_ && field_path.back().field == NULL) { + if (field_path.back().unknown_field_type == UnknownField::TYPE_GROUP) { + // Any changes to the subfields have already been printed. + return; + } + } else if (!report_modified_aggregates_) { + if (field_path.back().field->cpp_type() == + FieldDescriptor::CPPTYPE_MESSAGE) { + // Any changes to the subfields have already been printed. + return; + } + } + + printer_->Print("modified: "); + PrintPath(field_path, true); + if (CheckPathChanged(field_path)) { + printer_->Print(" -> "); + PrintPath(field_path, false); + } + printer_->Print(": "); + PrintValue(message1, field_path, true); + printer_->Print(" -> "); + PrintValue(message2, field_path, false); + printer_->Print("\n"); // Print for newlines. +} + +void MessageDifferencer::StreamReporter::ReportMoved( + const Message& message1, + const Message& message2, + const vector<SpecificField>& field_path) { + printer_->Print("moved: "); + PrintPath(field_path, true); + printer_->Print(" -> "); + PrintPath(field_path, false); + printer_->Print(" : "); + PrintValue(message1, field_path, true); + printer_->Print("\n"); // Print for newlines. +} + +void MessageDifferencer::StreamReporter::ReportMatched( + const Message& message1, + const Message& message2, + const vector<SpecificField>& field_path) { + printer_->Print("matched: "); + PrintPath(field_path, true); + if (CheckPathChanged(field_path)) { + printer_->Print(" -> "); + PrintPath(field_path, false); + } + printer_->Print(" : "); + PrintValue(message1, field_path, true); + printer_->Print("\n"); // Print for newlines. +} + +void MessageDifferencer::StreamReporter::ReportIgnored( + const Message& message1, + const Message& message2, + const vector<SpecificField>& field_path) { + printer_->Print("ignored: "); + PrintPath(field_path, true); + if (CheckPathChanged(field_path)) { + printer_->Print(" -> "); + PrintPath(field_path, false); + } + printer_->Print("\n"); // Print for newlines. +} + +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/message_differencer.h b/src/google/protobuf/util/message_differencer.h new file mode 100644 index 00000000..e002a0f3 --- /dev/null +++ b/src/google/protobuf/util/message_differencer.h @@ -0,0 +1,808 @@ +// 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. + +// Author: jschorr@google.com (Joseph Schorr) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file defines static methods and classes for comparing Protocol +// Messages. +// +// Aug. 2008: Added Unknown Fields Comparison for messages. +// Aug. 2009: Added different options to compare repeated fields. +// Apr. 2010: Moved field comparison to FieldComparator. + +#ifndef GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__ +#define GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__ + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <google/protobuf/descriptor.h> // FieldDescriptor +#include <google/protobuf/message.h> // Message +#include <google/protobuf/unknown_field_set.h> +#include <google/protobuf/util/field_comparator.h> + +namespace google { +namespace protobuf { + +class DynamicMessageFactory; +class FieldDescriptor; + +namespace io { +class ZeroCopyOutputStream; +class Printer; +} + +namespace util { + +class FieldContext; // declared below MessageDifferencer + +// A basic differencer that can be used to determine +// the differences between two specified Protocol Messages. If any differences +// are found, the Compare method will return false, and any differencer reporter +// specified via ReportDifferencesTo will have its reporting methods called (see +// below for implementation of the report). Based off of the original +// ProtocolDifferencer implementation in //net/proto/protocol-differencer.h +// (Thanks Todd!). +// +// MessageDifferencer REQUIRES that compared messages be the same type, defined +// as messages that share the same descriptor. If not, the behavior of this +// class is undefined. +// +// People disagree on what MessageDifferencer should do when asked to compare +// messages with different descriptors. Some people think it should always +// return false. Others expect it to try to look for similar fields and +// compare them anyway -- especially if the descriptors happen to be identical. +// If we chose either of these behaviors, some set of people would find it +// surprising, and could end up writing code expecting the other behavior +// without realizing their error. Therefore, we forbid that usage. +// +// This class is implemented based on the proto2 reflection. The performance +// should be good enough for normal usages. However, for places where the +// performance is extremely sensitive, there are several alternatives: +// - Comparing serialized string +// Downside: false negatives (there are messages that are the same but their +// serialized strings are different). +// - Equals code generator by compiler plugin (net/proto2/contrib/equals_plugin) +// Downside: more generated code; maintenance overhead for the additional rule +// (must be in sync with the original proto_library). +// +// Note on handling of google.protobuf.Any: MessageDifferencer automatically +// unpacks Any::value into a Message and compares its individual fields. +// Messages encoded in a repeated Any cannot be compared using TreatAsMap. +// +// +// Note on thread-safety: MessageDifferencer is *not* thread-safe. You need to +// guard it with a lock to use the same MessageDifferencer instance from +// multiple threads. Note that it's fine to call static comparison methods +// (like MessageDifferencer::Equals) concurrently. +class LIBPROTOBUF_EXPORT MessageDifferencer { + public: + // Determines whether the supplied messages are equal. Equality is defined as + // all fields within the two messages being set to the same value. Primitive + // fields and strings are compared by value while embedded messages/groups + // are compared as if via a recursive call. Use IgnoreField() and Compare() + // if some fields should be ignored in the comparison. + // + // This method REQUIRES that the two messages have the same + // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). + static bool Equals(const Message& message1, const Message& message2); + + // Determines whether the supplied messages are equivalent. Equivalency is + // defined as all fields within the two messages having the same value. This + // differs from the Equals method above in that fields with default values + // are considered set to said value automatically. For details on how default + // values are defined for each field type, see http://shortn/_x2Gv6XFrWt. + // Also, Equivalent() ignores unknown fields. Use IgnoreField() and Compare() + // if some fields should be ignored in the comparison. + // + // This method REQUIRES that the two messages have the same + // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). + static bool Equivalent(const Message& message1, const Message& message2); + + // Determines whether the supplied messages are approximately equal. + // Approximate equality is defined as all fields within the two messages + // being approximately equal. Primitive (non-float) fields and strings are + // compared by value, floats are compared using MathUtil::AlmostEquals() and + // embedded messages/groups are compared as if via a recursive call. Use + // IgnoreField() and Compare() if some fields should be ignored in the + // comparison. + // + // This method REQUIRES that the two messages have the same + // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). + static bool ApproximatelyEquals(const Message& message1, + const Message& message2); + + // Determines whether the supplied messages are approximately equivalent. + // Approximate equivalency is defined as all fields within the two messages + // being approximately equivalent. As in + // MessageDifferencer::ApproximatelyEquals, primitive (non-float) fields and + // strings are compared by value, floats are compared using + // MathUtil::AlmostEquals() and embedded messages/groups are compared as if + // via a recursive call. However, fields with default values are considered + // set to said value, as per MessageDiffencer::Equivalent. Use IgnoreField() + // and Compare() if some fields should be ignored in the comparison. + // + // This method REQUIRES that the two messages have the same + // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). + static bool ApproximatelyEquivalent(const Message& message1, + const Message& message2); + + // Identifies an individual field in a message instance. Used for field_path, + // below. + struct SpecificField { + // For known fields, "field" is filled in and "unknown_field_number" is -1. + // For unknown fields, "field" is NULL, "unknown_field_number" is the field + // number, and "unknown_field_type" is its type. + const FieldDescriptor* field; + int unknown_field_number; + UnknownField::Type unknown_field_type; + + // If this a repeated field, "index" is the index within it. For unknown + // fields, this is the index of the field among all unknown fields of the + // same field number and type. + int index; + + // If "field" is a repeated field which is being treated as a map or + // a set (see TreatAsMap() and TreatAsSet(), below), new_index indicates + // the index the position to which the element has moved. This only + // applies to ReportMoved() and (in the case of TreatAsMap()) + // ReportModified(). In all other cases, "new_index" will have the same + // value as "index". + int new_index; + + // For unknown fields, these are the pointers to the UnknownFieldSet + // containing the unknown fields. In certain cases (e.g. proto1's + // MessageSet, or nested groups of unknown fields), these may differ from + // the messages' internal UnknownFieldSets. + const UnknownFieldSet* unknown_field_set1; + const UnknownFieldSet* unknown_field_set2; + + // For unknown fields, these are the index of the field within the + // UnknownFieldSets. One or the other will be -1 when + // reporting an addition or deletion. + int unknown_field_index1; + int unknown_field_index2; + + SpecificField() + : field(NULL), + unknown_field_number(-1), + index(-1), + new_index(-1), + unknown_field_set1(NULL), + unknown_field_set2(NULL), + unknown_field_index1(-1), + unknown_field_index2(-1) {} + }; + + // Abstract base class from which all MessageDifferencer + // reporters derive. The five Report* methods below will be called when + // a field has been added, deleted, modified, moved, or matched. The third + // argument is a vector of FieldDescriptor pointers which describes the chain + // of fields that was taken to find the current field. For example, for a + // field found in an embedded message, the vector will contain two + // FieldDescriptors. The first will be the field of the embedded message + // itself and the second will be the actual field in the embedded message + // that was added/deleted/modified. + class LIBPROTOBUF_EXPORT Reporter { + public: + Reporter(); + virtual ~Reporter(); + + // Reports that a field has been added into Message2. + virtual void ReportAdded( + const Message& message1, const Message& message2, + const vector<SpecificField>& field_path) = 0; + + // Reports that a field has been deleted from Message1. + virtual void ReportDeleted( + const Message& message1, + const Message& message2, + const vector<SpecificField>& field_path) = 0; + + // Reports that the value of a field has been modified. + virtual void ReportModified( + const Message& message1, + const Message& message2, + const vector<SpecificField>& field_path) = 0; + + // Reports that a repeated field has been moved to another location. This + // only applies when using TreatAsSet or TreatAsMap() -- see below. Also + // note that for any given field, ReportModified and ReportMoved are + // mutually exclusive. If a field has been both moved and modified, then + // only ReportModified will be called. + virtual void ReportMoved( + const Message& message1, + const Message& message2, + const vector<SpecificField>& field_path) { } + + // Reports that two fields match. Useful for doing side-by-side diffs. + // This function is mutually exclusive with ReportModified and ReportMoved. + // Note that you must call set_report_matches(true) before calling Compare + // to make use of this function. + virtual void ReportMatched( + const Message& message1, + const Message& message2, + const vector<SpecificField>& field_path) { } + + // Reports that two fields would have been compared, but the + // comparison has been skipped because the field was marked as + // 'ignored' using IgnoreField(). This function is mutually + // exclusive with all the other Report() functions. + // + // The contract of ReportIgnored is slightly different than the + // other Report() functions, in that |field_path.back().index| is + // always equal to -1, even if the last field is repeated. This is + // because while the other Report() functions indicate where in a + // repeated field the action (Addition, Deletion, etc...) + // happened, when a repeated field is 'ignored', the differencer + // simply calls ReportIgnored on the repeated field as a whole and + // moves on without looking at its individual elements. + // + // Furthermore, ReportIgnored() does not indicate whether the + // fields were in fact equal or not, as Compare() does not inspect + // these fields at all. It is up to the Reporter to decide whether + // the fields are equal or not (perhaps with a second call to + // Compare()), if it cares. + virtual void ReportIgnored( + const Message& message1, + const Message& message2, + const vector<SpecificField>& field_path) { } + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reporter); + }; + + // MapKeyComparator is used to determine if two elements have the same key + // when comparing elements of a repeated field as a map. + class LIBPROTOBUF_EXPORT MapKeyComparator { + public: + MapKeyComparator(); + virtual ~MapKeyComparator(); + + virtual bool IsMatch(const Message& message1, + const Message& message2, + const vector<SpecificField>& parent_fields) const { + GOOGLE_CHECK(false) << "IsMatch() is not implemented."; + return false; + } + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapKeyComparator); + }; + + // Abstract base class from which all IgnoreCriteria derive. + // By adding IgnoreCriteria more complex ignore logic can be implemented. + // IgnoreCriteria are registed with AddIgnoreCriteria. For each compared + // field IsIgnored is called on each added IgnoreCriteria until one returns + // true or all return false. + // IsIgnored is called for fields where at least one side has a value. + class LIBPROTOBUF_EXPORT IgnoreCriteria { + public: + IgnoreCriteria(); + virtual ~IgnoreCriteria(); + + // Returns true if the field should be ignored. + virtual bool IsIgnored( + const Message& message1, + const Message& message2, + const FieldDescriptor* field, + const vector<SpecificField>& parent_fields) = 0; + }; + + // To add a Reporter, construct default here, then use ReportDifferencesTo or + // ReportDifferencesToString. + explicit MessageDifferencer(); + + ~MessageDifferencer(); + + enum MessageFieldComparison { + EQUAL, // Fields must be present in both messages + // for the messages to be considered the same. + EQUIVALENT, // Fields with default values are considered set + // for comparison purposes even if not explicitly + // set in the messages themselves. Unknown fields + // are ignored. + }; + + enum Scope { + FULL, // All fields of both messages are considered in the comparison. + PARTIAL // Only fields present in the first message are considered; fields + // set only in the second message will be skipped during + // comparison. + }; + + // DEPRECATED. Use FieldComparator::FloatComparison instead. + enum FloatComparison { + EXACT, // Floats and doubles are compared exactly. + APPROXIMATE // Floats and doubles are compared using the + // MathUtil::AlmostEquals method. + }; + + enum RepeatedFieldComparison { + AS_LIST, // Repeated fields are compared in order. Differing values at + // the same index are reported using ReportModified(). If the + // repeated fields have different numbers of elements, the + // unpaired elements are reported using ReportAdded() or + // ReportDeleted(). + AS_SET, // Treat all the repeated fields as sets by default. + // See TreatAsSet(), as below. + }; + + // The elements of the given repeated field will be treated as a set for + // diffing purposes, so different orderings of the same elements will be + // considered equal. Elements which are present on both sides of the + // comparison but which have changed position will be reported with + // ReportMoved(). Elements which only exist on one side or the other are + // reported with ReportAdded() and ReportDeleted() regardless of their + // positions. ReportModified() is never used for this repeated field. If + // the only differences between the compared messages is that some fields + // have been moved, then the comparison returns true. + // + // If the scope of comparison is set to PARTIAL, then in addition to what's + // above, extra values added to repeated fields of the second message will + // not cause the comparison to fail. + // + // Note that set comparison is currently O(k * n^2) (where n is the total + // number of elements, and k is the average size of each element). In theory + // it could be made O(n * k) with a more complex hashing implementation. Feel + // free to contribute one if the current implementation is too slow for you. + // If partial matching is also enabled, the time complexity will be O(k * n^2 + // + n^3) in which n^3 is the time complexity of the maximum matching + // algorithm. + // + // REQUIRES: field->is_repeated() + void TreatAsSet(const FieldDescriptor* field); + + // The elements of the given repeated field will be treated as a map for + // diffing purposes, with |key| being the map key. Thus, elements with the + // same key will be compared even if they do not appear at the same index. + // Differences are reported similarly to TreatAsSet(), except that + // ReportModified() is used to report elements with the same key but + // different values. Note that if an element is both moved and modified, + // only ReportModified() will be called. As with TreatAsSet, if the only + // differences between the compared messages is that some fields have been + // moved, then the comparison returns true. See TreatAsSet for notes on + // performance. + // + // REQUIRES: field->is_repeated() + // REQUIRES: field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE + // REQUIRES: key->containing_type() == field->message_type() + void TreatAsMap(const FieldDescriptor* field, const FieldDescriptor* key); + // Same as TreatAsMap except that this method will use multiple fields as + // the key in comparison. All specified fields in 'key_fields' should be + // present in the compared elements. Two elements will be treated as having + // the same key iff they have the same value for every specified field. There + // are two steps in the comparison process. The first one is key matching. + // Every element from one message will be compared to every element from + // the other message. Only fields in 'key_fields' are compared in this step + // to decide if two elements have the same key. The second step is value + // comparison. Those pairs of elements with the same key (with equal value + // for every field in 'key_fields') will be compared in this step. + // Time complexity of the first step is O(s * m * n ^ 2) where s is the + // average size of the fields specified in 'key_fields', m is the number of + // fields in 'key_fields' and n is the number of elements. If partial + // matching is enabled, an extra O(n^3) will be incured by the maximum + // matching algorithm. The second step is O(k * n) where k is the average + // size of each element. + void TreatAsMapWithMultipleFieldsAsKey( + const FieldDescriptor* field, + const vector<const FieldDescriptor*>& key_fields); + // Same as TreatAsMapWithMultipleFieldsAsKey, except that each of the field + // do not necessarily need to be a direct subfield. Each element in + // key_field_paths indicate a path from the message being compared, listing + // successive subfield to reach the key field. + // + // REQUIRES: + // for key_field_path in key_field_paths: + // key_field_path[0]->containing_type() == field->message_type() + // for i in [0, key_field_path.size() - 1): + // key_field_path[i+1]->containing_type() == + // key_field_path[i]->message_type() + // key_field_path[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE + // !key_field_path[i]->is_repeated() + void TreatAsMapWithMultipleFieldPathsAsKey( + const FieldDescriptor* field, + const vector<vector<const FieldDescriptor*> >& key_field_paths); + + // Uses a custom MapKeyComparator to determine if two elements have the same + // key when comparing a repeated field as a map. + // The caller is responsible to delete the key_comparator. + // This method varies from TreatAsMapWithMultipleFieldsAsKey only in the + // first key matching step. Rather than comparing some specified fields, it + // will invoke the IsMatch method of the given 'key_comparator' to decide if + // two elements have the same key. + void TreatAsMapUsingKeyComparator( + const FieldDescriptor* field, + const MapKeyComparator* key_comparator); + + // Add a custom ignore criteria that is evaluated in addition to the + // ignored fields added with IgnoreField. + // Takes ownership of ignore_criteria. + void AddIgnoreCriteria(IgnoreCriteria* ignore_criteria); + + // Indicates that any field with the given descriptor should be + // ignored for the purposes of comparing two messages. This applies + // to fields nested in the message structure as well as top level + // ones. When the MessageDifferencer encounters an ignored field, + // ReportIgnored is called on the reporter, if one is specified. + // + // The only place where the field's 'ignored' status is not applied is when + // it is being used as a key in a field passed to TreatAsMap or is one of + // the fields passed to TreatAsMapWithMultipleFieldsAsKey. + // In this case it is compared in key matching but after that it's ignored + // in value comparison. + void IgnoreField(const FieldDescriptor* field); + + // Sets the field comparator used to determine differences between protocol + // buffer fields. By default it's set to a DefaultFieldComparator instance. + // MessageDifferencer doesn't take ownership over the passed object. + // Note that this method must be called before Compare for the comparator to + // be used. + void set_field_comparator(FieldComparator* comparator); + + // DEPRECATED. Pass a DefaultFieldComparator instance instead. + // Sets the fraction and margin for the float comparison of a given field. + // Uses MathUtil::WithinFractionOrMargin to compare the values. + // NOTE: this method does nothing if differencer's field comparator has been + // set to a custom object. + // + // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or + // field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT + // REQUIRES: float_comparison_ == APPROXIMATE + void SetFractionAndMargin(const FieldDescriptor* field, double fraction, + double margin); + + // Sets the type of comparison (as defined in the MessageFieldComparison + // enumeration above) that is used by this differencer when determining how + // to compare fields in messages. + void set_message_field_comparison(MessageFieldComparison comparison); + + // Tells the differencer whether or not to report matches. This method must + // be called before Compare. The default for a new differencer is false. + void set_report_matches(bool report_matches) { + report_matches_ = report_matches; + } + + // Sets the scope of the comparison (as defined in the Scope enumeration + // above) that is used by this differencer when determining which fields to + // compare between the messages. + void set_scope(Scope scope); + + // Returns the current scope used by this differencer. + Scope scope(); + + // DEPRECATED. Pass a DefaultFieldComparator instance instead. + // Sets the type of comparison (as defined in the FloatComparison enumeration + // above) that is used by this differencer when comparing float (and double) + // fields in messages. + // NOTE: this method does nothing if differencer's field comparator has been + // set to a custom object. + void set_float_comparison(FloatComparison comparison); + + // Sets the type of comparison for repeated field (as defined in the + // RepeatedFieldComparison enumeration above) that is used by this + // differencer when compare repeated fields in messages. + void set_repeated_field_comparison(RepeatedFieldComparison comparison); + + // Compares the two specified messages, returning true if they are the same, + // false otherwise. If this method returns false, any changes between the + // two messages will be reported if a Reporter was specified via + // ReportDifferencesTo (see also ReportDifferencesToString). + // + // This method REQUIRES that the two messages have the same + // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). + bool Compare(const Message& message1, const Message& message2); + + // Same as above, except comparing only the list of fields specified by the + // two vectors of FieldDescriptors. + bool CompareWithFields(const Message& message1, const Message& message2, + const vector<const FieldDescriptor*>& message1_fields, + const vector<const FieldDescriptor*>& message2_fields); + + // Automatically creates a reporter that will output the differences + // found (if any) to the specified output string pointer. Note that this + // method must be called before Compare. + void ReportDifferencesToString(string* output); + + // Tells the MessageDifferencer to report differences via the specified + // reporter. Note that this method must be called before Compare for + // the reporter to be used. It is the responsibility of the caller to delete + // this object. + // If the provided pointer equals NULL, the MessageDifferencer stops reporting + // differences to any previously set reporters or output strings. + void ReportDifferencesTo(Reporter* reporter); + + // An implementation of the MessageDifferencer Reporter that outputs + // any differences found in human-readable form to the supplied + // ZeroCopyOutputStream or Printer. If a printer is used, the delimiter + // *must* be '$'. + class LIBPROTOBUF_EXPORT StreamReporter : public Reporter { + public: + explicit StreamReporter(io::ZeroCopyOutputStream* output); + explicit StreamReporter(io::Printer* printer); // delimiter '$' + virtual ~StreamReporter(); + + // When set to true, the stream reporter will also output aggregates nodes + // (i.e. messages and groups) whose subfields have been modified. When + // false, will only report the individual subfields. Defaults to false. + void set_report_modified_aggregates(bool report) { + report_modified_aggregates_ = report; + } + + // The following are implementations of the methods described above. + virtual void ReportAdded(const Message& message1, const Message& message2, + const vector<SpecificField>& field_path); + + virtual void ReportDeleted(const Message& message1, + const Message& message2, + const vector<SpecificField>& field_path); + + virtual void ReportModified(const Message& message1, + const Message& message2, + const vector<SpecificField>& field_path); + + virtual void ReportMoved(const Message& message1, + const Message& message2, + const vector<SpecificField>& field_path); + + virtual void ReportMatched(const Message& message1, + const Message& message2, + const vector<SpecificField>& field_path); + + virtual void ReportIgnored(const Message& message1, + const Message& message2, + const vector<SpecificField>& field_path); + + protected: + // Prints the specified path of fields to the buffer. + virtual void PrintPath(const vector<SpecificField>& field_path, + bool left_side); + + // Prints the value of fields to the buffer. left_side is true if the + // given message is from the left side of the comparison, false if it + // was the right. This is relevant only to decide whether to follow + // unknown_field_index1 or unknown_field_index2 when an unknown field + // is encountered in field_path. + virtual void PrintValue(const Message& message, + const vector<SpecificField>& field_path, + bool left_side); + + // Prints the specified path of unknown fields to the buffer. + virtual void PrintUnknownFieldValue(const UnknownField* unknown_field); + + // Just print a string + void Print(const string& str); + + private: + io::Printer* printer_; + bool delete_printer_; + bool report_modified_aggregates_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StreamReporter); + }; + + private: + // A MapKeyComparator to be used in TreatAsMapUsingKeyComparator. + // Implementation of this class needs to do field value comparison which + // relies on some private methods of MessageDifferencer. That's why this + // class is declared as a nested class of MessageDifferencer. + class MultipleFieldsMapKeyComparator; + // Returns true if field1's number() is less than field2's. + static bool FieldBefore(const FieldDescriptor* field1, + const FieldDescriptor* field2); + + // Combine the two lists of fields into the combined_fields output vector. + // All fields present in both lists will always be included in the combined + // list. Fields only present in one of the lists will only appear in the + // combined list if the corresponding fields_scope option is set to FULL. + void CombineFields(const vector<const FieldDescriptor*>& fields1, + Scope fields1_scope, + const vector<const FieldDescriptor*>& fields2, + Scope fields2_scope, + vector<const FieldDescriptor*>* combined_fields); + + // Internal version of the Compare method which performs the actual + // comparison. The parent_fields vector is a vector containing field + // descriptors of all fields accessed to get to this comparison operation + // (i.e. if the current message is an embedded message, the parent_fields + // vector will contain the field that has this embedded message). + bool Compare(const Message& message1, const Message& message2, + vector<SpecificField>* parent_fields); + + // Compares all the unknown fields in two messages. + bool CompareUnknownFields(const Message& message1, const Message& message2, + const google::protobuf::UnknownFieldSet&, + const google::protobuf::UnknownFieldSet&, + vector<SpecificField>* parent_fields); + + // Compares the specified messages for the requested field lists. The field + // lists are modified depending on comparison settings, and then passed to + // CompareWithFieldsInternal. + bool CompareRequestedFieldsUsingSettings( + const Message& message1, const Message& message2, + const vector<const FieldDescriptor*>& message1_fields, + const vector<const FieldDescriptor*>& message2_fields, + vector<SpecificField>* parent_fields); + + // Compares the specified messages with the specified field lists. + bool CompareWithFieldsInternal( + const Message& message1, const Message& message2, + const vector<const FieldDescriptor*>& message1_fields, + const vector<const FieldDescriptor*>& message2_fields, + vector<SpecificField>* parent_fields); + + // Compares the repeated fields, and report the error. + bool CompareRepeatedField(const Message& message1, const Message& message2, + const FieldDescriptor* field, + vector<SpecificField>* parent_fields); + + // Shorthand for CompareFieldValueUsingParentFields with NULL parent_fields. + bool CompareFieldValue(const Message& message1, + const Message& message2, + const FieldDescriptor* field, + int index1, + int index2); + + // Compares the specified field on the two messages, returning + // true if they are the same, false otherwise. For repeated fields, + // this method only compares the value in the specified index. This method + // uses Compare functions to recurse into submessages. + // The parent_fields vector is used in calls to a Reporter instance calls. + // It can be NULL, in which case the MessageDifferencer will create new + // list of parent messages if it needs to recursively compare the given field. + // To avoid confusing users you should not set it to NULL unless you modified + // Reporter to handle the change of parent_fields correctly. + bool CompareFieldValueUsingParentFields(const Message& message1, + const Message& message2, + const FieldDescriptor* field, + int index1, + int index2, + vector<SpecificField>* parent_fields); + + // Compares the specified field on the two messages, returning comparison + // result, as returned by appropriate FieldComparator. + FieldComparator::ComparisonResult GetFieldComparisonResult( + const Message& message1, const Message& message2, + const FieldDescriptor* field, int index1, int index2, + const FieldContext* field_context); + + // Check if the two elements in the repeated field are match to each other. + // if the key_comprator is NULL, this function returns true when the two + // elements are equal. + bool IsMatch(const FieldDescriptor* repeated_field, + const MapKeyComparator* key_comparator, + const Message* message1, const Message* message2, + const vector<SpecificField>& parent_fields, + int index1, int index2); + + // Returns true when this repeated field has been configured to be treated + // as a set. + bool IsTreatedAsSet(const FieldDescriptor* field); + + // Returns true when this repeated field is to be compared as a subset, ie. + // has been configured to be treated as a set or map and scope is set to + // PARTIAL. + bool IsTreatedAsSubset(const FieldDescriptor* field); + + // Returns true if this field is to be ignored when this + // MessageDifferencer compares messages. + bool IsIgnored( + const Message& message1, + const Message& message2, + const FieldDescriptor* field, + const vector<SpecificField>& parent_fields); + + // Returns MapKeyComparator* when this field has been configured to + // be treated as a map. If not, returns NULL. + const MapKeyComparator* GetMapKeyComparator(const FieldDescriptor* field); + + // Attempts to match indices of a repeated field, so that the contained values + // match. Clears output vectors and sets their values to indices of paired + // messages, ie. if message1[0] matches message2[1], then match_list1[0] == 1 + // and match_list2[1] == 0. The unmatched indices are indicated by -1. + // This method returns false if the match failed. However, it doesn't mean + // that the comparison succeeds when this method returns true (you need to + // double-check in this case). + bool MatchRepeatedFieldIndices(const Message& message1, + const Message& message2, + const FieldDescriptor* repeated_field, + const vector<SpecificField>& parent_fields, + vector<int>* match_list1, + vector<int>* match_list2); + + // If "any" is of type google.protobuf.Any, extract its payload using + // DynamicMessageFactory and store in "data". + bool UnpackAny(const Message& any, google::protobuf::scoped_ptr<Message>* data); + + // Checks if index is equal to new_index in all the specific fields. + static bool CheckPathChanged(const vector<SpecificField>& parent_fields); + + // Defines a map between field descriptors and their MapKeyComparators. + // Used for repeated fields when they are configured as TreatAsMap. + typedef map<const FieldDescriptor*, + const MapKeyComparator*> FieldKeyComparatorMap; + + // Defines a set to store field descriptors. Used for repeated fields when + // they are configured as TreatAsSet. + typedef set<const FieldDescriptor*> FieldSet; + + Reporter* reporter_; + DefaultFieldComparator default_field_comparator_; + FieldComparator* field_comparator_; + MessageFieldComparison message_field_comparison_; + Scope scope_; + RepeatedFieldComparison repeated_field_comparison_; + + FieldSet set_fields_; + // Keeps track of MapKeyComparators that are created within + // MessageDifferencer. These MapKeyComparators should be deleted + // before MessageDifferencer is destroyed. + // When TreatAsMap or TreatAsMapWithMultipleFieldsAsKey is called, we don't + // store the supplied FieldDescriptors directly. Instead, a new + // MapKeyComparator is created for comparison purpose. + vector<MapKeyComparator*> owned_key_comparators_; + FieldKeyComparatorMap map_field_key_comparator_; + vector<IgnoreCriteria*> ignore_criteria_; + + FieldSet ignored_fields_; + + bool compare_unknown_fields_; + bool report_matches_; + + string* output_string_; + + google::protobuf::scoped_ptr<DynamicMessageFactory> dynamic_message_factory_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageDifferencer); +}; + +// This class provides extra information to the FieldComparator::Compare +// function. +class LIBPROTOBUF_EXPORT FieldContext { + public: + explicit FieldContext( + vector<MessageDifferencer::SpecificField>* parent_fields) + : parent_fields_(parent_fields) {} + + vector<MessageDifferencer::SpecificField>* parent_fields() const { + return parent_fields_; + } + + private: + vector<MessageDifferencer::SpecificField>* parent_fields_; +}; + +} +} + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__ diff --git a/src/google/protobuf/util/message_differencer_unittest.cc b/src/google/protobuf/util/message_differencer_unittest.cc new file mode 100755 index 00000000..bd19f695 --- /dev/null +++ b/src/google/protobuf/util/message_differencer_unittest.cc @@ -0,0 +1,3132 @@ +// 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. + +// Author: jschorr@google.com (Joseph Schorr) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// TODO(ksroka): Move some of these tests to field_comparator_test.cc. + +#include <algorithm> +#include <string> +#include <vector> + + +#include <google/protobuf/util/field_comparator.h> +#include <google/protobuf/util/message_differencer.h> +#include <google/protobuf/util/message_differencer_unittest.pb.h> +#include <google/protobuf/text_format.h> +#include <google/protobuf/wire_format.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/any_test.pb.h> +#include <google/protobuf/map_unittest.pb.h> +#include <google/protobuf/unittest.pb.h> +#include <google/protobuf/map_test_util.h> +#include <google/protobuf/test_util.h> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/testing/googletest.h> +#include <gtest/gtest.h> + +namespace google { +namespace protobuf { + +namespace { + + +const FieldDescriptor* GetFieldDescriptor( + const Message& message, const string& field_name) { + vector<string> field_path = + Split(field_name, ".", true); + const Descriptor* descriptor = message.GetDescriptor(); + const FieldDescriptor* field = NULL; + for (int i = 0; i < field_path.size(); i++) { + field = descriptor->FindFieldByName(field_path[i]); + descriptor = field->message_type(); + } + return field; +} + +void ExpectEqualsWithDifferencer(util::MessageDifferencer* differencer, + const Message& msg1, + const Message& msg2) { + differencer->set_scope(util::MessageDifferencer::FULL); + EXPECT_TRUE(differencer->Compare(msg1, msg2)); + + differencer->set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer->Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicEqualityTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Compare + EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicInequalityTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.set_optional_int32(-1); + + // Compare + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, RepeatedFieldInequalityTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.add_repeated_int32(-1); + + // Compare + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, MapFieldEqualityTest) { + // Create the testing protos + unittest::TestMap msg1; + unittest::TestMap msg2; + + MapTestUtil::MapReflectionTester tester(unittest::TestMap::descriptor()); + tester.SetMapFieldsViaReflection(&msg1); + tester.SetMapFieldsViaReflection(&msg2); + tester.SwapMapsViaReflection(&msg1); + + // Compare + EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicPartialEqualityTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Compare + util::MessageDifferencer differencer; + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, PartialEqualityTestExtraField) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.clear_optional_int32(); + + // Compare + util::MessageDifferencer differencer; + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, PartialEqualityTestSkipRequiredField) { + // Create the testing protos + unittest::TestRequired msg1; + unittest::TestRequired msg2; + + msg1.set_a(401); + msg2.set_a(401); + msg2.set_b(402); + + // Compare + util::MessageDifferencer differencer; + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicPartialInequalityTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.set_optional_int32(-1); + + // Compare + util::MessageDifferencer differencer; + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, PartialInequalityMissingFieldTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg2.clear_optional_int32(); + + // Compare + util::MessageDifferencer differencer; + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, RepeatedFieldPartialInequalityTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.add_repeated_int32(-1); + + // Compare + util::MessageDifferencer differencer; + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicEquivalencyTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Compare + EXPECT_TRUE(util::MessageDifferencer::Equivalent(msg1, msg2)); +} + +TEST(MessageDifferencerTest, EquivalencyNotEqualTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.clear_optional_int32(); + msg2.set_optional_int32(0); + + // Compare + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); + EXPECT_TRUE(util::MessageDifferencer::Equivalent(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicInequivalencyTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.set_optional_int32(-1); + + // Compare + EXPECT_FALSE(util::MessageDifferencer::Equivalent(msg1, msg2)); +} + + +TEST(MessageDifferencerTest, BasicEquivalencyNonSetTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + // Compare + EXPECT_TRUE(util::MessageDifferencer::Equivalent(msg1, msg2)); +} + + +TEST(MessageDifferencerTest, BasicInequivalencyNonSetTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + msg1.set_optional_int32(-1); + + // Compare + EXPECT_FALSE(util::MessageDifferencer::Equivalent(msg1, msg2)); +} + + +TEST(MessageDifferencerTest, BasicPartialEquivalencyTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Compare + util::MessageDifferencer differencer; + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, PartialEquivalencyNotEqualTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.set_optional_int32(0); + msg2.clear_optional_int32(); + + // Compare + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); + util::MessageDifferencer differencer; + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, PartialEquivalencyTestExtraField) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.clear_optional_int32(); + + // Compare + util::MessageDifferencer differencer; + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, PartialEquivalencyTestSkipRequiredField) { + // Create the testing protos + unittest::TestRequired msg1; + unittest::TestRequired msg2; + + msg1.set_a(401); + msg2.set_a(401); + msg2.set_b(402); + + // Compare + util::MessageDifferencer differencer; + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicPartialInequivalencyTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.set_optional_int32(-1); + + // Compare + util::MessageDifferencer differencer; + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicPartialEquivalencyNonSetTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + // Compare + util::MessageDifferencer differencer; + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicPartialInequivalencyNonSetTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + msg1.set_optional_int32(-1); + + // Compare + util::MessageDifferencer differencer; + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, ApproximateEqualityTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Compare + EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, ApproximateModifiedEqualityTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + const float v1 = 2.300005f; + const float v2 = 2.300006f; + msg1.set_optional_float(v1); + msg2.set_optional_float(v2); + + // Compare + ASSERT_NE(v1, v2) << "Should not be the same: " << v1 << ", " << v2; + ASSERT_FLOAT_EQ(v1, v2) << "Should be approx. equal: " << v1 << ", " << v2; + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); + EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, ApproximateEquivalencyTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Compare + EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquivalent(msg1, + msg2)); +} + +TEST(MessageDifferencerTest, ApproximateModifiedEquivalencyTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Modify the approximateness requirement + const float v1 = 2.300005f; + const float v2 = 2.300006f; + msg1.set_optional_float(v1); + msg2.set_optional_float(v2); + + // Compare + ASSERT_NE(v1, v2) << "Should not be the same: " << v1 << ", " << v2; + ASSERT_FLOAT_EQ(v1, v2) << "Should be approx. equal: " << v1 << ", " << v2; + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); + EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquivalent(msg1, + msg2)); + + // Modify the equivalency requirement too + msg1.clear_optional_int32(); + msg2.set_optional_int32(0); + + // Compare. Now should only pass on ApproximatelyEquivalent + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); + EXPECT_FALSE(util::MessageDifferencer::Equivalent(msg1, msg2)); + EXPECT_FALSE(util::MessageDifferencer::ApproximatelyEquals(msg1, msg2)); + EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquivalent(msg1, + msg2)); +} + +TEST(MessageDifferencerTest, ApproximateInequivalencyTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Should fail on equivalency + msg1.set_optional_int32(-1); + EXPECT_FALSE(util::MessageDifferencer::ApproximatelyEquivalent(msg1, + msg2)); + + // Make these fields the same again. + msg1.set_optional_int32(0); + msg2.set_optional_int32(0); + EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquivalent(msg1, + msg2)); + + // Should fail on approximate equality check + const float v1 = 2.3f; + const float v2 = 9.3f; + msg1.set_optional_float(v1); + msg2.set_optional_float(v2); + EXPECT_FALSE(util::MessageDifferencer::ApproximatelyEquivalent(msg1, + msg2)); +} + +TEST(MessageDifferencerTest, WithinFractionOrMarginFloatTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Should fail on approximate equality check + const float v1 = 100.0f; + const float v2 = 109.9f; + msg1.set_optional_float(v1); + msg2.set_optional_float(v2); + + // Compare + util::MessageDifferencer differencer; + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + const FieldDescriptor* fd = + msg1.GetDescriptor()->FindFieldByName("optional_float"); + + // Set float comparison to exact, margin and fraction value should not matter. + differencer.set_float_comparison(util::MessageDifferencer::EXACT); + // Set margin for float comparison. + differencer.SetFractionAndMargin(fd, 0.0, 10.0); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Margin and fraction float comparison is activated when float comparison is + // set to approximate. + differencer.set_float_comparison(util::MessageDifferencer::APPROXIMATE); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Test out float comparison with fraction. + differencer.SetFractionAndMargin(fd, 0.2, 0.0); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Should fail since the fraction is smaller than error. + differencer.SetFractionAndMargin(fd, 0.01, 0.0); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Should pass if either fraction or margin are satisfied. + differencer.SetFractionAndMargin(fd, 0.01, 10.0); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Make sure that the margin and fraction only affects the field that it was + // set for. + msg1.set_default_float(v1); + msg2.set_default_float(v2); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + msg1.set_default_float(v1); + msg2.set_default_float(v1); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, WithinFractionOrMarginDoubleTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Should fail on approximate equality check + const double v1 = 100.0; + const double v2 = 109.9; + msg1.set_optional_double(v1); + msg2.set_optional_double(v2); + + // Compare + util::MessageDifferencer differencer; + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Set comparison to exact, margin and fraction value should not matter. + differencer.set_float_comparison(util::MessageDifferencer::EXACT); + // Set margin for float comparison. + const FieldDescriptor* fd = + msg1.GetDescriptor()->FindFieldByName("optional_double"); + differencer.SetFractionAndMargin(fd, 0.0, 10.0); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Margin and fraction comparison is activated when float comparison is + // set to approximate. + differencer.set_float_comparison(util::MessageDifferencer::APPROXIMATE); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Test out comparison with fraction. + differencer.SetFractionAndMargin(fd, 0.2, 0.0); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Should fail since the fraction is smaller than error. + differencer.SetFractionAndMargin(fd, 0.01, 0.0); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Should pass if either fraction or margin are satisfied. + differencer.SetFractionAndMargin(fd, 0.01, 10.0); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Make sure that the margin and fraction only affects the field that it was + // set for. + msg1.set_default_double(v1); + msg2.set_default_double(v2); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + msg1.set_default_double(v1); + msg2.set_default_double(v1); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, WithinDefaultFractionOrMarginDoubleTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Should fail on approximate equality check + const double v1 = 100.0; + const double v2 = 109.9; + msg1.set_optional_double(v1); + msg2.set_optional_double(v2); + + util::MessageDifferencer differencer; + + // Compare + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Set up a custom field comparitor, with a default fraction and margin for + // float and double comparison. + util::DefaultFieldComparator field_comparitor; + field_comparitor.SetDefaultFractionAndMargin(0.0, 10.0); + differencer.set_field_comparator(&field_comparitor); + + // Set comparison to exact, margin and fraction value should not matter. + field_comparitor.set_float_comparison(util::DefaultFieldComparator::EXACT); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Margin and fraction comparison is activated when float comparison is + // set to approximate. + field_comparitor.set_float_comparison( + util::DefaultFieldComparator::APPROXIMATE); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Test out comparison with fraction. + field_comparitor.SetDefaultFractionAndMargin(0.2, 0.0); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Should fail since the fraction is smaller than error. + field_comparitor.SetDefaultFractionAndMargin(0.01, 0.0); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Should pass if either fraction or margin are satisfied. + field_comparitor.SetDefaultFractionAndMargin(0.01, 10.0); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Make sure that the default margin and fraction affects all fields + msg1.set_default_double(v1); + msg2.set_default_double(v2); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicFieldOrderingsTest) { + // Create the testing protos + unittest::TestFieldOrderings msg1; + unittest::TestFieldOrderings msg2; + + TestUtil::SetAllFieldsAndExtensions(&msg1); + TestUtil::SetAllFieldsAndExtensions(&msg2); + + // Compare + EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2)); +} + + +TEST(MessageDifferencerTest, BasicFieldOrderingInequalityTest) { + // Create the testing protos + unittest::TestFieldOrderings msg1; + unittest::TestFieldOrderings msg2; + + TestUtil::SetAllFieldsAndExtensions(&msg1); + TestUtil::SetAllFieldsAndExtensions(&msg2); + + msg1.set_my_float(15.00); + msg2.set_my_float(16.00); + + // Compare + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicExtensionTest) { + // Create the testing protos + unittest::TestAllExtensions msg1; + unittest::TestAllExtensions msg2; + + TestUtil::SetAllExtensions(&msg1); + TestUtil::SetAllExtensions(&msg2); + + // Compare + EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2)); +} + + +TEST(MessageDifferencerTest, BasicExtensionInequalityTest) { + // Create the testing protos + unittest::TestAllExtensions msg1; + unittest::TestAllExtensions msg2; + + TestUtil::SetAllExtensions(&msg1); + TestUtil::SetAllExtensions(&msg2); + + msg1.SetExtension(unittest::optional_int32_extension, 101); + msg2.SetExtension(unittest::optional_int32_extension, 102); + + // Compare + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, OneofTest) { + // Create the testing protos + unittest::TestOneof2 msg1; + unittest::TestOneof2 msg2; + + TestUtil::SetOneof1(&msg1); + TestUtil::SetOneof1(&msg2); + + // Compare + EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, OneofInequalityTest) { + // Create the testing protos + unittest::TestOneof2 msg1; + unittest::TestOneof2 msg2; + + TestUtil::SetOneof1(&msg1); + TestUtil::SetOneof2(&msg2); + + // Compare + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, UnknownFieldPartialEqualTest) { + unittest::TestEmptyMessage empty1; + unittest::TestEmptyMessage empty2; + + UnknownFieldSet* unknown1 = empty1.mutable_unknown_fields(); + UnknownFieldSet* unknown2 = empty2.mutable_unknown_fields(); + + unknown1->AddVarint(243, 122); + unknown1->AddLengthDelimited(245, "abc"); + unknown1->AddGroup(246)->AddFixed32(248, 1); + unknown1->mutable_field(2)->mutable_group()->AddFixed32(248, 2); + + unknown2->AddVarint(243, 122); + unknown2->AddLengthDelimited(245, "abc"); + unknown2->AddGroup(246)->AddFixed32(248, 1); + unknown2->mutable_field(2)->mutable_group()->AddFixed32(248, 2); + + util::MessageDifferencer differencer; + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(empty1, empty2)); +} + +TEST(MessageDifferencerTest, SpecifiedFieldsEqualityAllTest) { + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + vector<const FieldDescriptor*> fields1; + vector<const FieldDescriptor*> fields2; + msg1.GetReflection()->ListFields(msg1, &fields1); + msg2.GetReflection()->ListFields(msg2, &fields2); + + util::MessageDifferencer differencer; + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields1, fields2)); +} + +TEST(MessageDifferencerTest, SpecifiedFieldsInequalityAllTest) { + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + + vector<const FieldDescriptor*> fields1; + vector<const FieldDescriptor*> fields2; + msg1.GetReflection()->ListFields(msg1, &fields1); + msg2.GetReflection()->ListFields(msg2, &fields2); + + util::MessageDifferencer differencer; + EXPECT_FALSE(differencer.CompareWithFields(msg1, msg2, fields1, fields2)); +} + +TEST(MessageDifferencerTest, SpecifiedFieldsEmptyListAlwaysSucceeds) { + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + + vector<const FieldDescriptor*> empty_fields; + + util::MessageDifferencer differencer; + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, + empty_fields, empty_fields)); + + TestUtil::SetAllFields(&msg2); + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, + empty_fields, empty_fields)); +} + +TEST(MessageDifferencerTest, SpecifiedFieldsCompareWithSelf) { + unittest::TestAllTypes msg1; + TestUtil::SetAllFields(&msg1); + + vector<const FieldDescriptor*> fields; + msg1.GetReflection()->ListFields(msg1, &fields); + + util::MessageDifferencer differencer; + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg1, fields, fields)); + + { + // Compare with a subset of fields. + vector<const FieldDescriptor*> compare_fields; + for (int i = 0; i < fields.size(); ++i) { + if (i % 2 == 0) { + compare_fields.push_back(fields[i]); + } + } + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg1, + compare_fields, compare_fields)); + } + { + // Specify a different set of fields to compare, even though we're using the + // same message. This should fail, since we are explicitly saying that the + // set of fields are different. + vector<const FieldDescriptor*> compare_fields1; + vector<const FieldDescriptor*> compare_fields2; + for (int i = 0; i < fields.size(); ++i) { + if (i % 2 == 0) { + compare_fields1.push_back(fields[i]); + } else { + compare_fields2.push_back(fields[i]); + } + } + EXPECT_FALSE(differencer.CompareWithFields( + msg1, msg1, compare_fields1, compare_fields2)); + } +} + +TEST(MessageDifferencerTest, SpecifiedFieldsEqualityAllShuffledTest) { + // This is a public function, so make sure there are no assumptions about the + // list of fields. Randomly shuffle them to make sure that they are properly + // ordered for comparison. + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + vector<const FieldDescriptor*> fields1; + vector<const FieldDescriptor*> fields2; + msg1.GetReflection()->ListFields(msg1, &fields1); + msg2.GetReflection()->ListFields(msg2, &fields2); + + std::random_shuffle(fields1.begin(), fields1.end()); + std::random_shuffle(fields2.begin(), fields2.end()); + + util::MessageDifferencer differencer; + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields1, fields2)); +} + +TEST(MessageDifferencerTest, SpecifiedFieldsSubsetEqualityTest) { + // Specify a set of fields to compare. All the fields are equal. + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + vector<const FieldDescriptor*> fields1; + msg1.GetReflection()->ListFields(msg1, &fields1); + + vector<const FieldDescriptor*> compare_fields; + // Only compare the field descriptors with even indices. + for (int i = 0; i < fields1.size(); ++i) { + if (i % 2 == 0) { + compare_fields.push_back(fields1[i]); + } + } + + util::MessageDifferencer differencer; + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, + compare_fields, compare_fields)); +} + +TEST(MessageDifferencerTest, + SpecifiedFieldsSubsetIgnoresOtherFieldDifferencesTest) { + // Specify a set of fields to compare, but clear all the other fields in one + // of the messages. This should fail a regular compare, but CompareWithFields + // should succeed. + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + vector<const FieldDescriptor*> fields1; + const Reflection* reflection = msg1.GetReflection(); + reflection->ListFields(msg1, &fields1); + + vector<const FieldDescriptor*> compare_fields; + // Only compare the field descriptors with even indices. + for (int i = 0; i < fields1.size(); ++i) { + if (i % 2 == 0) { + compare_fields.push_back(fields1[i]); + } else { + reflection->ClearField(&msg2, fields1[i]); + } + } + + util::MessageDifferencer differencer; + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, + compare_fields, compare_fields)); +} + +TEST(MessageDifferencerTest, SpecifiedFieldsDetectsDifferencesTest) { + // Change all of the repeated fields in one of the messages, and use only + // those fields for comparison. + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + TestUtil::ModifyRepeatedFields(&msg2); + + vector<const FieldDescriptor*> fields1; + msg1.GetReflection()->ListFields(msg1, &fields1); + + vector<const FieldDescriptor*> compare_fields; + // Only compare the repeated field descriptors. + for (int i = 0; i < fields1.size(); ++i) { + if (fields1[i]->is_repeated()) { + compare_fields.push_back(fields1[i]); + } + } + + util::MessageDifferencer differencer; + EXPECT_FALSE(differencer.CompareWithFields(msg1, msg2, + compare_fields, compare_fields)); +} + +TEST(MessageDifferencerTest, SpecifiedFieldsEquivalenceAllTest) { + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + vector<const FieldDescriptor*> fields1; + vector<const FieldDescriptor*> fields2; + msg1.GetReflection()->ListFields(msg1, &fields1); + msg2.GetReflection()->ListFields(msg2, &fields2); + + util::MessageDifferencer differencer; + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields1, fields2)); +} + +TEST(MessageDifferencerTest, + SpecifiedFieldsEquivalenceIgnoresOtherFieldDifferencesTest) { + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + const Descriptor* desc = msg1.GetDescriptor(); + + const FieldDescriptor* optional_int32_desc = + desc->FindFieldByName("optional_int32"); + const FieldDescriptor* optional_int64_desc = + desc->FindFieldByName("optional_int64"); + const FieldDescriptor* default_int64_desc = + desc->FindFieldByName("default_int64"); + ASSERT_TRUE(optional_int32_desc != NULL); + ASSERT_TRUE(optional_int64_desc != NULL); + ASSERT_TRUE(default_int64_desc != NULL); + msg1.set_optional_int32(0); + msg2.set_optional_int64(0); + msg1.set_default_int64(default_int64_desc->default_value_int64()); + + // Set a field to a non-default value so we know that field selection is + // actually doing something. + msg2.set_optional_uint64(23); + + vector<const FieldDescriptor*> fields1; + vector<const FieldDescriptor*> fields2; + fields1.push_back(optional_int32_desc); + fields1.push_back(default_int64_desc); + + fields2.push_back(optional_int64_desc); + + util::MessageDifferencer differencer; + EXPECT_FALSE(differencer.CompareWithFields(msg1, msg2, fields1, fields2)); + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields1, fields2)); +} + +TEST(MessageDifferencerTest, RepeatedFieldSetTest_SetOfSet) { + // Create the testing protos + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + item->add_ra(1); item->add_ra(2); item->add_ra(3); + item = msg1.add_item(); + item->add_ra(5); item->add_ra(6); + item = msg1.add_item(); + item->add_ra(1); item->add_ra(3); + item = msg1.add_item(); + item->add_ra(6); item->add_ra(7); item->add_ra(8); + + item = msg2.add_item(); + item->add_ra(6); item->add_ra(5); + item = msg2.add_item(); + item->add_ra(6); item->add_ra(8); item->add_ra(7); + item = msg2.add_item(); + item->add_ra(1); item->add_ra(3); + item = msg2.add_item(); + item->add_ra(3); item->add_ra(2); item->add_ra(1); + + // Compare + util::MessageDifferencer differencer; + differencer.set_repeated_field_comparison(util::MessageDifferencer::AS_SET); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, RepeatedFieldSetTest_Combination) { + // Create the testing protos + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + // Treat "item" as Map, with key = "a" + // Treat "item.ra" also as Set + // Treat "rv" as Set + // Treat "rw" as List + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + item->set_a(3); + item->add_ra(1); item->add_ra(2); item->add_ra(3); + item = msg1.add_item(); + item->set_a(4); + item->add_ra(5); item->add_ra(6); + item = msg1.add_item(); + item->set_a(1); + item->add_ra(1); item->add_ra(3); + item = msg1.add_item(); + item->set_a(2); + item->add_ra(6); item->add_ra(7); item->add_ra(8); + + item = msg2.add_item(); + item->set_a(4); + item->add_ra(6); item->add_ra(5); + item = msg2.add_item(); + item->set_a(2); + item->add_ra(6); item->add_ra(8); item->add_ra(7); + item = msg2.add_item(); + item->set_a(1); + item->add_ra(1); item->add_ra(3); + item = msg2.add_item(); + item->set_a(3); + item->add_ra(3); item->add_ra(2); item->add_ra(1); + + msg1.add_rv(3); + msg1.add_rv(4); + msg1.add_rv(7); + msg1.add_rv(0); + msg2.add_rv(4); + msg2.add_rv(3); + msg2.add_rv(0); + msg2.add_rv(7); + + msg1.add_rw("nothing"); msg2.add_rw("nothing"); + msg1.add_rw("should"); msg2.add_rw("should"); + msg1.add_rw("change"); msg2.add_rw("change"); + + // Compare + util::MessageDifferencer differencer; + differencer.TreatAsMap(msg1.GetDescriptor()->FindFieldByName("item"), + item->GetDescriptor()->FindFieldByName("a")); + differencer.TreatAsSet(msg1.GetDescriptor()->FindFieldByName("rv")); + differencer.TreatAsSet(item->GetDescriptor()->FindFieldByName("ra")); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, RepeatedFieldMapTest_Partial) { + protobuf_unittest::TestDiffMessage msg1; + // message msg1 { + // item { a: 1; b: "11" } + // } + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + item->set_a(1); + item->set_b("11"); + + protobuf_unittest::TestDiffMessage msg2; + // message msg2 { + // item { a: 2; b: "22" } + // item { a: 1; b: "11" } + // } + item = msg2.add_item(); + item->set_a(2); + item->set_b("22"); + item = msg2.add_item(); + item->set_a(1); + item->set_b("11"); + + // Compare + util::MessageDifferencer differencer; + differencer.TreatAsMap(GetFieldDescriptor(msg1, "item"), + GetFieldDescriptor(msg1, "item.a")); + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, RepeatedFieldSetTest_Duplicates) { + protobuf_unittest::TestDiffMessage a, b, c; + // message a: { + // rv: 0 + // rv: 1 + // rv: 0 + // } + a.add_rv(0); + a.add_rv(1); + a.add_rv(0); + // message b: { + // rv: 0 + // rv: 0 + // rv: 1 + // } + b.add_rv(0); + b.add_rv(0); + b.add_rv(1); + // message c: { + // rv: 0 + // rv: 1 + // } + c.add_rv(0); + c.add_rv(1); + util::MessageDifferencer differencer; + differencer.TreatAsSet(GetFieldDescriptor(a, "rv")); + EXPECT_TRUE(differencer.Compare(b, a)); + EXPECT_FALSE(differencer.Compare(c, a)); +} + +TEST(MessageDifferencerTest, RepeatedFieldSetTest_PartialSimple) { + protobuf_unittest::TestDiffMessage a, b, c; + // message a: { + // rm { c: 1 } + // rm { c: 0 } + // } + a.add_rm()->set_c(1); + a.add_rm()->set_c(0); + // message b: { + // rm { c: 1 } + // rm {} + // } + b.add_rm()->set_c(1); + b.add_rm(); + // message c: { + // rm {} + // rm { c: 1 } + // } + c.add_rm(); + c.add_rm()->set_c(1); + util::MessageDifferencer differencer; + differencer.set_scope(util::MessageDifferencer::PARTIAL); + differencer.TreatAsSet(GetFieldDescriptor(a, "rm")); + EXPECT_TRUE(differencer.Compare(b, a)); + EXPECT_TRUE(differencer.Compare(c, a)); +} + +TEST(MessageDifferencerTest, RepeatedFieldSetTest_Partial) { + protobuf_unittest::TestDiffMessage msg1, msg2; + // message msg1: { + // rm { a: 1 } + // rm { b: 2 } + // rm { c: 3 } + // } + msg1.add_rm()->set_a(1); + msg1.add_rm()->set_b(2); + msg1.add_rm()->set_c(3); + // message msg2: { + // rm { a: 1; c: 3 } + // rm { b: 2; c: 3 } + // rm { b: 2 } + // } + protobuf_unittest::TestField* field = msg2.add_rm(); + field->set_a(1); + field->set_c(3); + field = msg2.add_rm(); + field->set_b(2); + field->set_c(3); + field = msg2.add_rm(); + field->set_b(2); + + util::MessageDifferencer differencer; + differencer.set_scope(util::MessageDifferencer::PARTIAL); + differencer.TreatAsSet(GetFieldDescriptor(msg1, "rm")); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, RepeatedFieldMapTest_MultipleFieldsAsKey) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + // Treat "item" as Map, with key = ("a", "ra") + // Treat "item.ra" as Set + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + // key => value: (1, {2, 3}) => "a" + item->set_a(1); + item->add_ra(2); + item->add_ra(3); + item->set_b("a"); + item = msg1.add_item(); + // key => value: (2, {1, 3}) => "b" + item->set_a(2); + item->add_ra(1); + item->add_ra(3); + item->set_b("b"); + item = msg1.add_item(); + // key => value: (1, {1, 3}) => "c" + item->set_a(1); + item->add_ra(1); + item->add_ra(3); + item->set_b("c"); + + item = msg2.add_item(); + // key => value: (1, {1, 3}) => "c" + item->set_a(1); + item->add_ra(3); + item->add_ra(1); + item->set_b("c"); + item = msg2.add_item(); + // key => value: (1, {2, 3}) => "a" + item->set_a(1); + item->add_ra(3); + item->add_ra(2); + item->set_b("a"); + item = msg2.add_item(); + // key => value: (2, {1, 3}) => "b" + item->set_a(2); + item->add_ra(3); + item->add_ra(1); + item->set_b("b"); + + // Compare + util::MessageDifferencer differencer; + differencer.TreatAsSet(GetFieldDescriptor(msg1, "item.ra")); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + vector<const FieldDescriptor*> key_fields; + key_fields.push_back(GetFieldDescriptor(msg1, "item.a")); + key_fields.push_back(GetFieldDescriptor(msg1, "item.ra")); + differencer.TreatAsMapWithMultipleFieldsAsKey( + GetFieldDescriptor(msg1, "item"), key_fields); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Introduce some differences. + msg1.clear_item(); + msg2.clear_item(); + item = msg1.add_item(); + item->set_a(4); + item->add_ra(5); + item->add_ra(6); + item->set_b("hello"); + item = msg2.add_item(); + item->set_a(4); + item->add_ra(6); + item->add_ra(5); + item->set_b("world"); + string output; + differencer.ReportDifferencesToString(&output); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + EXPECT_EQ( + "moved: item[0].ra[0] -> item[0].ra[1] : 5\n" + "moved: item[0].ra[1] -> item[0].ra[0] : 6\n" + "modified: item[0].b: \"hello\" -> \"world\"\n", + output); +} + +TEST(MessageDifferencerTest, RepeatedFieldMapTest_MultipleFieldPathsAsKey) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + // Treat "item" as Map, with key = ("m.a", "m.rc") + // Treat "item.m.rc" as Set + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + // key => value: (1, {2, 3}) => "a" + item->mutable_m()->set_a(1); + item->mutable_m()->add_rc(2); + item->mutable_m()->add_rc(3); + item->set_b("a"); + item = msg1.add_item(); + // key => value: (2, {1, 3}) => "b" + item->mutable_m()->set_a(2); + item->mutable_m()->add_rc(1); + item->mutable_m()->add_rc(3); + item->set_b("b"); + item = msg1.add_item(); + // key => value: (1, {1, 3}) => "c" + item->mutable_m()->set_a(1); + item->mutable_m()->add_rc(1); + item->mutable_m()->add_rc(3); + item->set_b("c"); + + item = msg2.add_item(); + // key => value: (1, {1, 3}) => "c" + item->mutable_m()->set_a(1); + item->mutable_m()->add_rc(3); + item->mutable_m()->add_rc(1); + item->set_b("c"); + item = msg2.add_item(); + // key => value: (1, {2, 3}) => "a" + item->mutable_m()->set_a(1); + item->mutable_m()->add_rc(3); + item->mutable_m()->add_rc(2); + item->set_b("a"); + item = msg2.add_item(); + // key => value: (2, {1, 3}) => "b" + item->mutable_m()->set_a(2); + item->mutable_m()->add_rc(3); + item->mutable_m()->add_rc(1); + item->set_b("b"); + + // Compare + util::MessageDifferencer differencer; + differencer.TreatAsSet(GetFieldDescriptor(msg1, "item.m.rc")); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + vector<vector<const FieldDescriptor*> > key_field_paths; + vector<const FieldDescriptor*> key_field_path1; + key_field_path1.push_back(GetFieldDescriptor(msg1, "item.m")); + key_field_path1.push_back(GetFieldDescriptor(msg1, "item.m.a")); + vector<const FieldDescriptor*> key_field_path2; + key_field_path2.push_back(GetFieldDescriptor(msg1, "item.m")); + key_field_path2.push_back(GetFieldDescriptor(msg1, "item.m.rc")); + key_field_paths.push_back(key_field_path1); + key_field_paths.push_back(key_field_path2); + differencer.TreatAsMapWithMultipleFieldPathsAsKey( + GetFieldDescriptor(msg1, "item"), key_field_paths); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Introduce some differences. + msg1.clear_item(); + msg2.clear_item(); + item = msg1.add_item(); + item->mutable_m()->set_a(4); + item->mutable_m()->add_rc(5); + item->mutable_m()->add_rc(6); + item->set_b("hello"); + item = msg2.add_item(); + item->mutable_m()->set_a(4); + item->mutable_m()->add_rc(6); + item->mutable_m()->add_rc(5); + item->set_b("world"); + string output; + differencer.ReportDifferencesToString(&output); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + EXPECT_EQ( + "modified: item[0].b: \"hello\" -> \"world\"\n" + "moved: item[0].m.rc[0] -> item[0].m.rc[1] : 5\n" + "moved: item[0].m.rc[1] -> item[0].m.rc[0] : 6\n", + output); +} + +TEST(MessageDifferencerTest, RepeatedFieldMapTest_IgnoredKeyFields) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + // Treat "item" as Map, with key = ("a", "ra") + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + item->set_a(1); + item->add_ra(2); + item->set_b("hello"); + item = msg2.add_item(); + item->set_a(1); + item->add_ra(3); + item->set_b("world"); + // Compare + util::MessageDifferencer differencer; + vector<const FieldDescriptor*> key_fields; + key_fields.push_back(GetFieldDescriptor(msg1, "item.a")); + key_fields.push_back(GetFieldDescriptor(msg1, "item.ra")); + differencer.TreatAsMapWithMultipleFieldsAsKey( + GetFieldDescriptor(msg1, "item"), key_fields); + string output; + differencer.ReportDifferencesToString(&output); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + EXPECT_EQ( + "added: item[0]: { a: 1 ra: 3 b: \"world\" }\n" + "deleted: item[0]: { a: 1 ra: 2 b: \"hello\" }\n", + output); + // Ignored fields that are listed as parts of the key are still used + // in key comparison, but they're not used in value comparison. + differencer.IgnoreField(GetFieldDescriptor(msg1, "item.ra")); + output.clear(); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + EXPECT_EQ( + "added: item[0]: { a: 1 ra: 3 b: \"world\" }\n" + "deleted: item[0]: { a: 1 ra: 2 b: \"hello\" }\n", + output); + // Ignoring a field in the key is different from treating the left fields + // as key. That is: + // (key = ("a", "ra") && ignore "ra") != (key = ("a") && ignore "ra") + util::MessageDifferencer differencer2; + differencer2.TreatAsMap(GetFieldDescriptor(msg1, "item"), + GetFieldDescriptor(msg1, "item.a")); + differencer2.IgnoreField(GetFieldDescriptor(msg1, "item.ra")); + output.clear(); + differencer2.ReportDifferencesToString(&output); + EXPECT_FALSE(differencer2.Compare(msg1, msg2)); + EXPECT_EQ( + "ignored: item[0].ra\n" + "modified: item[0].b: \"hello\" -> \"world\"\n", + output); +} + +static const char* const kIgnoredFields[] = {"rm.b", "rm.m.b"}; + +class TestIgnorer : public util::MessageDifferencer::IgnoreCriteria { + public: + bool IsIgnored( + const Message& message1, const Message& message2, + const FieldDescriptor* field, + const vector<util::MessageDifferencer::SpecificField>& parent_fields) + override { + string name = ""; + for (int i = 0; i < parent_fields.size(); ++i) { + name += parent_fields[i].field->name() + "."; + } + name += field->name(); + for (int i = 0; i < GOOGLE_ARRAYSIZE(kIgnoredFields); ++i) { + if (name.compare(kIgnoredFields[i]) == 0) { + return true; + } + } + return false; + } +}; + +TEST(MessageDifferencerTest, TreatRepeatedFieldAsSetWithIgnoredFields) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + TextFormat::MergeFromString("rm { a: 11\n b: 12 }", &msg1); + TextFormat::MergeFromString("rm { a: 11\n b: 13 }", &msg2); + util::MessageDifferencer differ; + differ.TreatAsSet(GetFieldDescriptor(msg1, "rm")); + differ.AddIgnoreCriteria(new TestIgnorer); + EXPECT_TRUE(differ.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, TreatRepeatedFieldAsMapWithIgnoredKeyFields) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + TextFormat::MergeFromString("rm { a: 11\n m { a: 12\n b: 13\n } }", &msg1); + TextFormat::MergeFromString("rm { a: 11\n m { a: 12\n b: 14\n } }", &msg2); + util::MessageDifferencer differ; + differ.TreatAsMap(GetFieldDescriptor(msg1, "rm"), + GetFieldDescriptor(msg1, "rm.m")); + differ.AddIgnoreCriteria(new TestIgnorer); + EXPECT_TRUE(differ.Compare(msg1, msg2)); +} + +// Takes the product of all elements of item.ra as the key for key comparison. +class ValueProductMapKeyComparator + : public util::MessageDifferencer::MapKeyComparator { + public: + virtual bool IsMatch(const Message &message1, + const Message &message2) const { + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + // FieldDescriptor for item.ra + const FieldDescriptor* ra_field = + message1.GetDescriptor()->FindFieldByName("ra"); + // Get the product of all elements in item.ra + int result1 = 1, result2 = 1; + for (int i = 0; i < reflection1->FieldSize(message1, ra_field); ++i) { + result1 *= reflection1->GetRepeatedInt32(message1, ra_field, i); + } + for (int i = 0; i < reflection2->FieldSize(message2, ra_field); ++i) { + result2 *= reflection2->GetRepeatedInt32(message2, ra_field, i); + } + return result1 == result2; + } +}; + +TEST(MessageDifferencerTest, RepeatedFieldMapTest_CustomMapKeyComparator) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + // Treat "item" as Map, using custom key comparator to determine if two + // elements have the same key. + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + item->add_ra(6); + item->add_ra(35); + item->set_b("hello"); + item = msg2.add_item(); + item->add_ra(10); + item->add_ra(21); + item->set_b("hello"); + util::MessageDifferencer differencer; + ValueProductMapKeyComparator key_comparator; + differencer.TreatAsMapUsingKeyComparator( + GetFieldDescriptor(msg1, "item"), &key_comparator); + string output; + differencer.ReportDifferencesToString(&output); + // Though the above two messages have different values for item.ra, they + // are regarded as having the same key because 6 * 35 == 10 * 21. That's + // how the key comparator determines if the two have the same key. + // However, in value comparison, all fields of the message are taken into + // consideration, so they are different because their item.ra fields have + // different values using normal value comparison. + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + EXPECT_EQ( + "modified: item[0].ra[0]: 6 -> 10\n" + "modified: item[0].ra[1]: 35 -> 21\n", + output); + differencer.IgnoreField(GetFieldDescriptor(msg1, "item.ra")); + output.clear(); + // item.ra is ignored in value comparison, so the two messages equal. + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + EXPECT_EQ("ignored: item[0].ra\n", output); +} + +TEST(MessageDifferencerTest, RepeatedFieldSetTest_Subset) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + msg1.add_rv(3); + msg1.add_rv(8); + msg1.add_rv(2); + msg2.add_rv(2); + msg2.add_rv(3); + msg2.add_rv(5); + msg2.add_rv(8); + + util::MessageDifferencer differencer; + + // Fail with only partial scope set. + differencer.set_scope(util::MessageDifferencer::PARTIAL); + differencer.set_repeated_field_comparison(util::MessageDifferencer::AS_LIST); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Fail with only set-like comparison set. + differencer.set_scope(util::MessageDifferencer::FULL); + differencer.set_repeated_field_comparison(util::MessageDifferencer::AS_SET); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Succeed with scope and repeated field comparison set properly. + differencer.set_scope(util::MessageDifferencer::PARTIAL); + differencer.set_repeated_field_comparison(util::MessageDifferencer::AS_SET); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, IgnoreField_Single) { + protobuf_unittest::TestField msg1; + protobuf_unittest::TestField msg2; + + msg1.set_c(3); + msg1.add_rc(1); + + msg2.set_c(5); + msg2.add_rc(1); + + util::MessageDifferencer differencer; + differencer.IgnoreField(GetFieldDescriptor(msg1, "c")); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); +} + +TEST(MessageDifferencerTest, IgnoreField_Repeated) { + protobuf_unittest::TestField msg1; + protobuf_unittest::TestField msg2; + + msg1.set_c(3); + msg1.add_rc(1); + msg1.add_rc(2); + + msg2.set_c(3); + msg2.add_rc(1); + msg2.add_rc(3); + + util::MessageDifferencer differencer; + differencer.IgnoreField(GetFieldDescriptor(msg1, "rc")); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); +} + +TEST(MessageDifferencerTest, IgnoreField_Message) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + protobuf_unittest::TestField* field; + + field = msg1.add_rm(); + field->set_c(3); + + field = msg2.add_rm(); + field->set_c(4); + + util::MessageDifferencer differencer; + differencer.IgnoreField(GetFieldDescriptor(msg1, "rm")); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); +} + +TEST(MessageDifferencerTest, IgnoreField_Group) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + protobuf_unittest::TestDiffMessage::Item* item; + + item = msg1.add_item(); + item->set_a(3); + + item = msg2.add_item(); + item->set_a(4); + + util::MessageDifferencer differencer; + differencer.IgnoreField(GetFieldDescriptor(msg1, "item")); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); +} + +TEST(MessageDifferencerTest, IgnoreField_Missing) { + protobuf_unittest::TestField msg1; + protobuf_unittest::TestField msg2; + + msg1.set_c(3); + msg1.add_rc(1); + + msg2.add_rc(1); + + util::MessageDifferencer differencer; + differencer.IgnoreField(GetFieldDescriptor(msg1, "c")); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); + ExpectEqualsWithDifferencer(&differencer, msg2, msg1); +} + +TEST(MessageDifferencerTest, IgnoreField_Multiple) { + protobuf_unittest::TestField msg1; + protobuf_unittest::TestField msg2; + + msg1.set_c(3); + msg1.add_rc(1); + msg1.add_rc(2); + + msg2.set_c(5); + msg2.add_rc(1); + msg2.add_rc(3); + + const FieldDescriptor* c = GetFieldDescriptor(msg1, "c"); + const FieldDescriptor* rc = GetFieldDescriptor(msg1, "rc"); + + { // Ignore c + util::MessageDifferencer differencer; + differencer.IgnoreField(c); + + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + } + { // Ignore rc + util::MessageDifferencer differencer; + differencer.IgnoreField(rc); + + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + } + { // Ignore both + util::MessageDifferencer differencer; + differencer.IgnoreField(c); + differencer.IgnoreField(rc); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); + } +} + +TEST(MessageDifferencerTest, IgnoreField_NestedMessage) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + protobuf_unittest::TestField* field; + + field = msg1.add_rm(); + field->set_c(3); + field->add_rc(1); + + field = msg2.add_rm(); + field->set_c(4); + field->add_rc(1); + + util::MessageDifferencer differencer; + differencer.IgnoreField(GetFieldDescriptor(msg1, "rm.c")); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); +} + +TEST(MessageDifferencerTest, IgnoreField_NestedGroup) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + protobuf_unittest::TestDiffMessage::Item* item; + + item = msg1.add_item(); + item->set_a(3); + item->set_b("foo"); + + item = msg2.add_item(); + item->set_a(4); + item->set_b("foo"); + + util::MessageDifferencer differencer; + differencer.IgnoreField(GetFieldDescriptor(msg1, "item.a")); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); +} + +TEST(MessageDifferencerTest, IgnoreField_InsideSet) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + protobuf_unittest::TestDiffMessage::Item* item; + + item = msg1.add_item(); + item->set_a(1); + item->set_b("foo"); + item->add_ra(1); + + item = msg1.add_item(); + item->set_a(2); + item->set_b("bar"); + item->add_ra(2); + + item = msg2.add_item(); + item->set_a(2); + item->set_b("bar"); + item->add_ra(2); + + item = msg2.add_item(); + item->set_a(1); + item->set_b("baz"); + item->add_ra(1); + + const FieldDescriptor* item_desc = GetFieldDescriptor(msg1, "item"); + const FieldDescriptor* b = GetFieldDescriptor(msg1, "item.b"); + + util::MessageDifferencer differencer; + differencer.IgnoreField(b); + differencer.TreatAsSet(item_desc); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); +} + +TEST(MessageDifferencerTest, IgnoreField_InsideMap) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + protobuf_unittest::TestDiffMessage::Item* item; + + item = msg1.add_item(); + item->set_a(1); + item->set_b("foo"); + item->add_ra(1); + + item = msg1.add_item(); + item->set_a(2); + item->set_b("bar"); + item->add_ra(2); + + item = msg2.add_item(); + item->set_a(2); + item->set_b("bar"); + item->add_ra(2); + + item = msg2.add_item(); + item->set_a(1); + item->set_b("baz"); + item->add_ra(1); + + const FieldDescriptor* item_desc = GetFieldDescriptor(msg1, "item"); + const FieldDescriptor* a = GetFieldDescriptor(msg1, "item.a"); + const FieldDescriptor* b = GetFieldDescriptor(msg1, "item.b"); + + util::MessageDifferencer differencer; + differencer.IgnoreField(b); + differencer.TreatAsMap(item_desc, a); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); +} + +TEST(MessageDifferencerTest, IgnoreField_DoesNotIgnoreKey) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + protobuf_unittest::TestDiffMessage::Item* item; + + item = msg1.add_item(); + item->set_a(1); + item->set_b("foo"); + item->add_ra(1); + + item = msg2.add_item(); + item->set_a(2); + item->set_b("foo"); + item->add_ra(1); + + const FieldDescriptor* item_desc = GetFieldDescriptor(msg1, "item"); + const FieldDescriptor* a = GetFieldDescriptor(msg1, "item.a"); + + util::MessageDifferencer differencer; + differencer.IgnoreField(a); + differencer.TreatAsMap(item_desc, a); + + EXPECT_FALSE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, IgnoreField_TrumpsCompareWithFields) { + protobuf_unittest::TestField msg1; + protobuf_unittest::TestField msg2; + + msg1.set_c(3); + msg1.add_rc(1); + msg1.add_rc(2); + + msg2.set_c(3); + msg2.add_rc(1); + msg2.add_rc(3); + + const FieldDescriptor* c = GetFieldDescriptor(msg1, "c"); + const FieldDescriptor* rc = GetFieldDescriptor(msg1, "rc"); + + vector<const FieldDescriptor*> fields; + fields.push_back(c); + fields.push_back(rc); + + util::MessageDifferencer differencer; + differencer.IgnoreField(rc); + + differencer.set_scope(util::MessageDifferencer::FULL); + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields, fields)); + + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields, fields)); +} + + +// Test class to save a copy of the last field_context.parent_fields() vector +// passed to the comparison function. +class ParentSavingFieldComparator : public util::FieldComparator { + public: + ParentSavingFieldComparator() {} + + virtual ComparisonResult Compare( + const google::protobuf::Message& message_1, + const google::protobuf::Message& message_2, + const google::protobuf::FieldDescriptor* field, + int index_1, int index_2, + const google::protobuf::util::FieldContext* field_context) { + if (field_context) + parent_fields_ = *(field_context->parent_fields()); + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + return RECURSE; + } else { + return SAME; + } + } + + vector<google::protobuf::util::MessageDifferencer::SpecificField> parent_fields() { + return parent_fields_; + } + + private: + vector<google::protobuf::util::MessageDifferencer::SpecificField> parent_fields_; +}; + +// Tests if MessageDifferencer sends the parent fields in the FieldContext +// parameter. +TEST(MessageDifferencerTest, FieldContextParentFieldsTest) { + protobuf_unittest::TestDiffMessage msg1; + msg1.add_rm()->set_c(1); + protobuf_unittest::TestDiffMessage msg2; + msg2.add_rm()->set_c(1); + + ParentSavingFieldComparator field_comparator; + util::MessageDifferencer differencer; + differencer.set_field_comparator(&field_comparator); + differencer.Compare(msg1, msg2); + + // We want only one parent with the name "rm" + ASSERT_EQ(1, field_comparator.parent_fields().size()); + EXPECT_EQ("rm", field_comparator.parent_fields()[0].field->name()); +} + + +class ComparisonTest : public testing::Test { + protected: + ComparisonTest() : use_equivalency_(false), repeated_field_as_set_(false) { + // Setup the test. + TestUtil::SetAllFields(&proto1_); + TestUtil::SetAllFields(&proto2_); + + TestUtil::SetAllExtensions(&proto1ex_); + TestUtil::SetAllExtensions(&proto2ex_); + + TestUtil::SetAllFieldsAndExtensions(&orderings_proto1_); + TestUtil::SetAllFieldsAndExtensions(&orderings_proto2_); + + unknown1_ = empty1_.mutable_unknown_fields(); + unknown2_ = empty2_.mutable_unknown_fields(); + } + + ~ComparisonTest() { } + + void SetSpecialFieldOption(const Message& message, + util::MessageDifferencer* d) { + if (!ignored_field_.empty()) { + d->IgnoreField(GetFieldDescriptor(message, ignored_field_)); + } + + if (repeated_field_as_set_) { + d->set_repeated_field_comparison(util::MessageDifferencer::AS_SET); + } + + if (!set_field_.empty()) { + d->TreatAsSet(GetFieldDescriptor(message, set_field_)); + } + + if (!map_field_.empty() && !map_key_.empty()) { + d->TreatAsMap(GetFieldDescriptor(message, map_field_), + GetFieldDescriptor(message, map_field_ + "." + map_key_)); + } + } + + string Run(const Message& msg1, const Message& msg2) { + string output; + + // Setup the comparison. + util::MessageDifferencer differencer; + differencer.ReportDifferencesToString(&output); + + if (use_equivalency_) { + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + } + + SetSpecialFieldOption(msg1, &differencer); + + // Conduct the comparison. + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + return output; + } + + string Run() { + return Run(proto1_, proto2_); + } + + string RunOrder() { + return Run(orderings_proto1_, orderings_proto2_); + } + + string RunEx() { + return Run(proto1ex_, proto2ex_); + } + + string RunDiff() { + return Run(proto1diff_, proto2diff_); + } + + string RunUn() { + return Run(empty1_, empty2_); + } + + void use_equivalency() { + use_equivalency_ = true; + } + + void repeated_field_as_set() { + repeated_field_as_set_ = true; + } + + void field_as_set(const string& field) { + set_field_ = field; + } + + void field_as_map(const string& field, const string& key) { + map_field_ = field; + map_key_ = key; + } + + void ignore_field(const string& field) { + ignored_field_ = field; + } + + unittest::TestAllTypes proto1_; + unittest::TestAllTypes proto2_; + + unittest::TestFieldOrderings orderings_proto1_; + unittest::TestFieldOrderings orderings_proto2_; + + unittest::TestAllExtensions proto1ex_; + unittest::TestAllExtensions proto2ex_; + + unittest::TestDiffMessage proto1diff_; + unittest::TestDiffMessage proto2diff_; + + unittest::TestEmptyMessage empty1_; + unittest::TestEmptyMessage empty2_; + + UnknownFieldSet* unknown1_; + UnknownFieldSet* unknown2_; + + bool use_equivalency_; + bool repeated_field_as_set_; + + string set_field_; + string map_field_; + string map_key_; + string ignored_field_; +}; + +// Basic tests. +TEST_F(ComparisonTest, AdditionTest) { + proto1_.clear_optional_int32(); + + EXPECT_EQ("added: optional_int32: 101\n", + Run()); +} + +TEST_F(ComparisonTest, Addition_OrderTest) { + orderings_proto1_.clear_my_int(); + + EXPECT_EQ("added: my_int: 1\n", + RunOrder()); +} + +TEST_F(ComparisonTest, DeletionTest) { + proto2_.clear_optional_int32(); + + EXPECT_EQ("deleted: optional_int32: 101\n", + Run()); +} + +TEST_F(ComparisonTest, Deletion_OrderTest) { + orderings_proto2_.clear_my_string(); + + EXPECT_EQ("deleted: my_string: \"foo\"\n", + RunOrder()); +} + +TEST_F(ComparisonTest, RepeatedDeletionTest) { + proto2_.clear_repeated_int32(); + + EXPECT_EQ("deleted: repeated_int32[0]: 201\n" + "deleted: repeated_int32[1]: 301\n", + Run()); +} + +TEST_F(ComparisonTest, ModificationTest) { + proto1_.set_optional_int32(-1); + + EXPECT_EQ("modified: optional_int32: -1 -> 101\n", + Run()); +} + +// Basic equivalency tests. +TEST_F(ComparisonTest, EquivalencyAdditionTest) { + use_equivalency(); + + proto1_.clear_optional_int32(); + + EXPECT_EQ("modified: optional_int32: 0 -> 101\n", + Run()); +} + +TEST_F(ComparisonTest, EquivalencyDeletionTest) { + use_equivalency(); + + proto2_.clear_optional_int32(); + + EXPECT_EQ("modified: optional_int32: 101 -> 0\n", + Run()); +} + +// Group tests. +TEST_F(ComparisonTest, GroupAdditionTest) { + proto1_.mutable_optionalgroup()->clear_a(); + + EXPECT_EQ("added: optionalgroup.a: 117\n", + Run()); +} + +TEST_F(ComparisonTest, GroupDeletionTest) { + proto2_.mutable_optionalgroup()->clear_a(); + + EXPECT_EQ("deleted: optionalgroup.a: 117\n", + Run()); +} + +TEST_F(ComparisonTest, GroupModificationTest) { + proto1_.mutable_optionalgroup()->set_a(2); + + EXPECT_EQ("modified: optionalgroup.a: 2 -> 117\n", + Run()); +} + +TEST_F(ComparisonTest, GroupFullAdditionTest) { + proto1_.clear_optionalgroup(); + + // Note the difference in the output between this and GroupAdditionTest. + EXPECT_EQ("added: optionalgroup: { a: 117 }\n", + Run()); +} + +TEST_F(ComparisonTest, GroupFullDeletionTest) { + proto2_.clear_optionalgroup(); + + EXPECT_EQ("deleted: optionalgroup: { a: 117 }\n", + Run()); +} + +TEST_F(ComparisonTest, RepeatedSetOptionTest) { + repeated_field_as_set(); + + proto2_.clear_repeatedgroup(); + proto1_.clear_repeatedgroup(); + proto1_.add_repeatedgroup()->set_a(317); + proto2_.add_repeatedgroup()->set_a(909); + proto2_.add_repeatedgroup()->set_a(907); + proto1_.add_repeatedgroup()->set_a(904); + proto1_.add_repeatedgroup()->set_a(907); + proto1_.add_repeatedgroup()->set_a(909); + + EXPECT_EQ("moved: repeatedgroup[2] -> repeatedgroup[1] : { a: 907 }\n" + "moved: repeatedgroup[3] -> repeatedgroup[0] : { a: 909 }\n" + "deleted: repeatedgroup[0]: { a: 317 }\n" + "deleted: repeatedgroup[1]: { a: 904 }\n", + Run()); +} + +TEST_F(ComparisonTest, RepeatedSetOptionTest_Ex) { + repeated_field_as_set(); + + proto1ex_.ClearExtension(protobuf_unittest::repeated_nested_message_extension); + proto2ex_.ClearExtension(protobuf_unittest::repeated_nested_message_extension); + proto2ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension) + ->set_bb(909); + proto2ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension) + ->set_bb(907); + proto1ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension) + ->set_bb(904); + proto1ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension) + ->set_bb(907); + proto1ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension) + ->set_bb(909); + + EXPECT_EQ("moved: (protobuf_unittest.repeated_nested_message_extension)[2] ->" + " (protobuf_unittest.repeated_nested_message_extension)[0] :" + " { bb: 909 }\n" + "deleted: (protobuf_unittest.repeated_nested_message_extension)[0]:" + " { bb: 904 }\n", + RunEx()); +} + +TEST_F(ComparisonTest, RepeatedMapFieldTest_Group) { + field_as_map("repeatedgroup", "a"); + proto1_.clear_repeatedgroup(); + proto2_.clear_repeatedgroup(); + + proto1_.add_repeatedgroup()->set_a(317); // deleted + proto1_.add_repeatedgroup()->set_a(904); // deleted + proto1_.add_repeatedgroup()->set_a(907); // moved from + proto1_.add_repeatedgroup()->set_a(909); // moved from + + proto2_.add_repeatedgroup()->set_a(909); // moved to + proto2_.add_repeatedgroup()->set_a(318); // added + proto2_.add_repeatedgroup()->set_a(907); // moved to + + EXPECT_EQ("moved: repeatedgroup[3] -> repeatedgroup[0] : { a: 909 }\n" + "added: repeatedgroup[1]: { a: 318 }\n" + "deleted: repeatedgroup[0]: { a: 317 }\n" + "deleted: repeatedgroup[1]: { a: 904 }\n", + Run()); +} + +TEST_F(ComparisonTest, RepeatedMapFieldTest_MessageKey) { + // Use m as key, but use b as value. + field_as_map("item", "m"); + + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + + // The following code creates one deletion, one addition and two moved fields + // on the messages. + item->mutable_m()->set_c(0); + item->set_b("first"); + item = msg1.add_item(); + item->mutable_m()->set_c(2); + item->set_b("second"); + item = msg1.add_item(); item->set_b("null"); // empty key moved + item = msg1.add_item(); + item->mutable_m()->set_c(3); + item->set_b("third"); // deletion + item = msg1.add_item(); + item->mutable_m()->set_c(2); + item->set_b("second"); // duplicated key ( deletion ) + item = msg2.add_item(); + item->mutable_m()->set_c(2); + item->set_b("second"); // modification + item = msg2.add_item(); + item->mutable_m()->set_c(4); + item->set_b("fourth"); // addition + item = msg2.add_item(); + item->mutable_m()->set_c(0); + item->set_b("fist"); // move with change + item = msg2.add_item(); item->set_b("null"); + + EXPECT_EQ( + "modified: item[0].b -> item[2].b: \"first\" -> \"fist\"\n" + "moved: item[1] -> item[0] : { b: \"second\" m { c: 2 } }\n" + "moved: item[2] -> item[3] : { b: \"null\" }\n" + "added: item[1]: { b: \"fourth\" m { c: 4 } }\n" + "deleted: item[3]: { b: \"third\" m { c: 3 } }\n" + "deleted: item[4]: { b: \"second\" m { c: 2 } }\n", + Run(msg1, msg2)); +} + +TEST_F(ComparisonTest, RepeatedFieldSetTest_SetOfSet) { + repeated_field_as_set(); + // Create the testing protos + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + item->add_ra(1); item->add_ra(2); item->add_ra(3); + item = msg1.add_item(); + item->add_ra(5); item->add_ra(6); + item = msg1.add_item(); + item->add_ra(1); item->add_ra(3); + item = msg1.add_item(); + item->add_ra(6); item->add_ra(7); item->add_ra(8); + + item = msg2.add_item(); + item->add_ra(6); item->add_ra(5); + item = msg2.add_item(); + item->add_ra(6); item->add_ra(8); + item = msg2.add_item(); + item->add_ra(1); item->add_ra(3); + item = msg2.add_item(); + item->add_ra(3); item->add_ra(2); item->add_ra(1); + + // Compare + EXPECT_EQ("moved: item[0].ra[0] -> item[3].ra[2] : 1\n" + "moved: item[0].ra[2] -> item[3].ra[0] : 3\n" + "moved: item[0] -> item[3] : { ra: 1 ra: 2 ra: 3 }\n" + "moved: item[1].ra[0] -> item[0].ra[1] : 5\n" + "moved: item[1].ra[1] -> item[0].ra[0] : 6\n" + "moved: item[1] -> item[0] : { ra: 5 ra: 6 }\n" + "added: item[1]: { ra: 6 ra: 8 }\n" + "deleted: item[3]: { ra: 6 ra: 7 ra: 8 }\n", + Run(msg1, msg2)); +} + +TEST_F(ComparisonTest, RepeatedMapFieldTest_RepeatedKey) { + // used rb as a key, but b is the value. + repeated_field_as_set(); + field_as_map("item", "rb"); + + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + item->add_rb("a"); + item->add_rb("b"); + item->set_b("first"); + + item = msg2.add_item(); + item->add_rb("c"); + item->set_b("second"); + + item = msg2.add_item(); + item->add_rb("b"); + item->add_rb("a"); + item->set_b("fist"); + + + EXPECT_EQ("modified: item[0].b -> item[1].b: \"first\" -> \"fist\"\n" + "moved: item[0].rb[0] -> item[1].rb[1] : \"a\"\n" + "moved: item[0].rb[1] -> item[1].rb[0] : \"b\"\n" + "added: item[0]: { b: \"second\" rb: \"c\" }\n", + Run(msg1, msg2)); +} + +TEST_F(ComparisonTest, RepeatedMapFieldTest_RepeatedMessageKey) { + field_as_map("item", "rm"); + + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + protobuf_unittest::TestField* key = item->add_rm(); + key->set_c(2); key->add_rc(10); key->add_rc(10); + item = msg1.add_item(); key = item->add_rm(); + key->set_c(0); key->add_rc(1); key->add_rc(2); + key = item->add_rm(); + key->set_c(0); + item->add_rb("first"); + + item = msg2.add_item(); + item->CopyFrom(msg1.item(1)); + item->add_rb("second"); + + EXPECT_EQ("added: item[0].rb[1]: \"second\"\n" + "deleted: item[0]: { rm { c: 2 rc: 10 rc: 10 } }\n", + Run(msg1, msg2)); +} + +TEST_F(ComparisonTest, RepeatedSetOptionTest_Unknown) { + // Currently, as_set option doens't have affects on unknown field. + // If needed, this feature will be added by request. + repeated_field_as_set(); + unknown1_->AddGroup(245)->AddFixed32(248, 1); + unknown2_->AddGroup(245)->AddFixed32(248, 3); + unknown2_->AddGroup(245)->AddFixed32(248, 1); + + // We expect it behaves the same as normal comparison. + EXPECT_EQ("modified: 245[0].248[0]: 0x00000001 -> 0x00000003\n" + "added: 245[1]: { ... }\n", + RunUn()); +} + +TEST_F(ComparisonTest, Matching_Unknown) { + unknown1_->AddGroup(245)->AddFixed32(248, 1); + unknown2_->AddGroup(245)->AddFixed32(248, 1); + unknown1_->AddGroup(245)->AddFixed32(248, 3); + unknown2_->AddGroup(245)->AddFixed32(248, 3); + unknown2_->AddLengthDelimited(242, "cat"); + unknown2_->AddGroup(246)->AddFixed32(248, 4); + + // report_match is false so only added/modified fields are expected. + EXPECT_EQ("added: 242[0]: \"cat\"\n" + "added: 246[0]: { ... }\n", + RunUn()); +} + +TEST_F(ComparisonTest, RepeatedSetFieldTest) { + field_as_set("repeatedgroup"); + + proto1_.clear_repeatedgroup(); + proto2_.clear_repeatedgroup(); + proto2_.add_repeatedgroup()->set_a(909); + proto2_.add_repeatedgroup()->set_a(907); + proto1_.add_repeatedgroup()->set_a(317); + proto1_.add_repeatedgroup()->set_a(904); + proto1_.add_repeatedgroup()->set_a(907); + proto1_.add_repeatedgroup()->set_a(909); + + EXPECT_EQ("moved: repeatedgroup[2] -> repeatedgroup[1] : { a: 907 }\n" + "moved: repeatedgroup[3] -> repeatedgroup[0] : { a: 909 }\n" + "deleted: repeatedgroup[0]: { a: 317 }\n" + "deleted: repeatedgroup[1]: { a: 904 }\n", + Run()); +} + +// Embedded message tests. +TEST_F(ComparisonTest, EmbeddedAdditionTest) { + proto1_.mutable_optional_nested_message()->clear_bb(); + + EXPECT_EQ("added: optional_nested_message.bb: 118\n", + Run()); +} + +TEST_F(ComparisonTest, EmbeddedDeletionTest) { + proto2_.mutable_optional_nested_message()->clear_bb(); + + EXPECT_EQ("deleted: optional_nested_message.bb: 118\n", + Run()); +} + +TEST_F(ComparisonTest, EmbeddedModificationTest) { + proto1_.mutable_optional_nested_message()->set_bb(2); + + EXPECT_EQ("modified: optional_nested_message.bb: 2 -> 118\n", + Run()); +} + +TEST_F(ComparisonTest, EmbeddedFullAdditionTest) { + proto1_.clear_optional_nested_message(); + + EXPECT_EQ("added: optional_nested_message: { bb: 118 }\n", + Run()); +} + +TEST_F(ComparisonTest, EmbeddedPartialAdditionTest) { + proto1_.clear_optional_nested_message(); + proto2_.mutable_optional_nested_message()->clear_bb(); + + EXPECT_EQ("added: optional_nested_message: { }\n", + Run()); +} + +TEST_F(ComparisonTest, EmbeddedFullDeletionTest) { + proto2_.clear_optional_nested_message(); + + EXPECT_EQ("deleted: optional_nested_message: { bb: 118 }\n", + Run()); +} + +// Repeated element tests. +TEST_F(ComparisonTest, BasicRepeatedTest) { + proto1_.clear_repeated_int32(); + proto2_.clear_repeated_int32(); + + proto1_.add_repeated_int32(500); + proto1_.add_repeated_int32(501); + proto1_.add_repeated_int32(502); + proto1_.add_repeated_int32(503); + proto1_.add_repeated_int32(500); + + proto2_.add_repeated_int32(500); + proto2_.add_repeated_int32(509); + proto2_.add_repeated_int32(502); + proto2_.add_repeated_int32(504); + + EXPECT_EQ("modified: repeated_int32[1]: 501 -> 509\n" + "modified: repeated_int32[3]: 503 -> 504\n" + "deleted: repeated_int32[4]: 500\n", + Run()); +} + +TEST_F(ComparisonTest, BasicRepeatedTest_SetOption) { + repeated_field_as_set(); + proto1_.clear_repeated_int32(); + proto2_.clear_repeated_int32(); + + proto1_.add_repeated_int32(501); + proto1_.add_repeated_int32(502); + proto1_.add_repeated_int32(503); + proto1_.add_repeated_int32(500); + proto1_.add_repeated_int32(500); + + proto2_.add_repeated_int32(500); + proto2_.add_repeated_int32(509); + proto2_.add_repeated_int32(503); + proto2_.add_repeated_int32(502); + proto2_.add_repeated_int32(504); + + EXPECT_EQ("moved: repeated_int32[1] -> repeated_int32[3] : 502\n" + "moved: repeated_int32[3] -> repeated_int32[0] : 500\n" + "added: repeated_int32[1]: 509\n" + "added: repeated_int32[4]: 504\n" + "deleted: repeated_int32[0]: 501\n" + "deleted: repeated_int32[4]: 500\n", + Run()); +} + +TEST_F(ComparisonTest, BasicRepeatedTest_SetField) { + field_as_set("repeated_int32"); + proto1_.clear_repeated_int32(); + proto2_.clear_repeated_int32(); + + proto1_.add_repeated_int32(501); + proto1_.add_repeated_int32(502); + proto1_.add_repeated_int32(503); + proto1_.add_repeated_int32(500); + proto1_.add_repeated_int32(500); + + proto2_.add_repeated_int32(500); + proto2_.add_repeated_int32(509); + proto2_.add_repeated_int32(503); + proto2_.add_repeated_int32(502); + proto2_.add_repeated_int32(504); + + EXPECT_EQ("moved: repeated_int32[1] -> repeated_int32[3] : 502\n" + "moved: repeated_int32[3] -> repeated_int32[0] : 500\n" + "added: repeated_int32[1]: 509\n" + "added: repeated_int32[4]: 504\n" + "deleted: repeated_int32[0]: 501\n" + "deleted: repeated_int32[4]: 500\n", + Run()); +} + +// Multiple action tests. +TEST_F(ComparisonTest, AddDeleteTest) { + proto1_.clear_optional_int32(); + proto2_.clear_optional_int64(); + + EXPECT_EQ("added: optional_int32: 101\n" + "deleted: optional_int64: 102\n", + Run()); +} + +TEST_F(ComparisonTest, AddDelete_FieldOrderingTest) { + orderings_proto1_.ClearExtension(unittest::my_extension_string); + orderings_proto2_.clear_my_int(); + + EXPECT_EQ("deleted: my_int: 1\n" + "added: (protobuf_unittest.my_extension_string): \"bar\"\n", + RunOrder()); +} + +TEST_F(ComparisonTest, AllThreeTest) { + proto1_.clear_optional_int32(); + proto2_.clear_optional_float(); + proto2_.set_optional_string("hello world!"); + + EXPECT_EQ("added: optional_int32: 101\n" + "deleted: optional_float: 111\n" + "modified: optional_string: \"115\" -> \"hello world!\"\n", + Run()); +} + +TEST_F(ComparisonTest, SandwhichTest) { + proto1_.clear_optional_int64(); + proto1_.clear_optional_uint32(); + + proto2_.clear_optional_uint64(); + + EXPECT_EQ("added: optional_int64: 102\n" + "added: optional_uint32: 103\n" + "deleted: optional_uint64: 104\n", + Run()); +} + +TEST_F(ComparisonTest, IgnoredNoChangeTest) { + proto1diff_.set_v(3); + proto2diff_.set_v(3); + proto2diff_.set_w("foo"); + + ignore_field("v"); + + EXPECT_EQ("ignored: v\n" + "added: w: \"foo\"\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredAddTest) { + proto2diff_.set_v(3); + proto2diff_.set_w("foo"); + + ignore_field("v"); + + EXPECT_EQ("ignored: v\n" + "added: w: \"foo\"\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredDeleteTest) { + proto1diff_.set_v(3); + proto2diff_.set_w("foo"); + + ignore_field("v"); + + EXPECT_EQ("ignored: v\n" + "added: w: \"foo\"\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredModifyTest) { + proto1diff_.set_v(3); + proto2diff_.set_v(4); + proto2diff_.set_w("foo"); + + ignore_field("v"); + + EXPECT_EQ("ignored: v\n" + "added: w: \"foo\"\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredRepeatedAddTest) { + proto1diff_.add_rv(3); + proto1diff_.add_rv(4); + + proto2diff_.add_rv(3); + proto2diff_.add_rv(4); + proto2diff_.add_rv(5); + + proto2diff_.set_w("foo"); + + ignore_field("rv"); + + EXPECT_EQ("ignored: rv\n" + "added: w: \"foo\"\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredRepeatedDeleteTest) { + proto1diff_.add_rv(3); + proto1diff_.add_rv(4); + proto1diff_.add_rv(5); + + proto2diff_.add_rv(3); + proto2diff_.add_rv(4); + + proto2diff_.set_w("foo"); + + ignore_field("rv"); + + EXPECT_EQ("ignored: rv\n" + "added: w: \"foo\"\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredRepeatedModifyTest) { + proto1diff_.add_rv(3); + proto1diff_.add_rv(4); + + proto2diff_.add_rv(3); + proto2diff_.add_rv(5); + + proto2diff_.set_w("foo"); + + ignore_field("rv"); + + EXPECT_EQ("ignored: rv\n" + "added: w: \"foo\"\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredWholeNestedMessage) { + proto1diff_.mutable_m()->set_c(3); + proto2diff_.mutable_m()->set_c(4); + + proto2diff_.set_w("foo"); + + ignore_field("m"); + + EXPECT_EQ("added: w: \"foo\"\n" + "ignored: m\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredNestedField) { + proto1diff_.mutable_m()->set_c(3); + proto2diff_.mutable_m()->set_c(4); + + proto2diff_.set_w("foo"); + + ignore_field("m.c"); + + EXPECT_EQ("added: w: \"foo\"\n" + "ignored: m.c\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredRepeatedNested) { + proto1diff_.add_rm()->set_c(0); + proto1diff_.add_rm()->set_c(1); + proto2diff_.add_rm()->set_c(2); + proto2diff_.add_rm()->set_c(3); + + proto2diff_.set_w("foo"); + + ignore_field("rm.c"); + + EXPECT_EQ("ignored: rm[0].c\n" + "ignored: rm[1].c\n" + "added: w: \"foo\"\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredNestedRepeated) { + proto1diff_.mutable_m()->add_rc(23); + proto1diff_.mutable_m()->add_rc(24); + proto2diff_.mutable_m()->add_rc(25); + + proto2diff_.set_w("foo"); + + ignore_field("m.rc"); + + EXPECT_EQ("added: w: \"foo\"\n" + "ignored: m.rc\n", + RunDiff()); +} + +TEST_F(ComparisonTest, ExtensionTest) { + proto1ex_.SetExtension(unittest::optional_int32_extension, 401); + proto2ex_.SetExtension(unittest::optional_int32_extension, 402); + + proto1ex_.ClearExtension(unittest::optional_int64_extension); + proto2ex_.SetExtension(unittest::optional_int64_extension, 403); + + EXPECT_EQ( + "modified: (protobuf_unittest.optional_int32_extension): 401 -> 402\n" + "added: (protobuf_unittest.optional_int64_extension): 403\n", + RunEx()); +} + +TEST_F(ComparisonTest, MatchedUnknownFieldTagTest) { + unknown1_->AddVarint(240, 122); + unknown2_->AddVarint(240, 121); + unknown1_->AddFixed32(241, 1); + unknown2_->AddFixed64(241, 2); + unknown1_->AddLengthDelimited(242, "cat"); + unknown2_->AddLengthDelimited(242, "dog"); + + EXPECT_EQ( + "modified: 240[0]: 122 -> 121\n" + "deleted: 241[0]: 0x00000001\n" + "added: 241[0]: 0x0000000000000002\n" + "modified: 242[0]: \"cat\" -> \"dog\"\n", + RunUn()); +} + +TEST_F(ComparisonTest, UnmatchedUnknownFieldTagTest) { + unknown1_->AddFixed32(243, 1); + unknown2_->AddVarint(244, 2); + unknown2_->AddVarint(244, 4); + + EXPECT_EQ( + "deleted: 243[0]: 0x00000001\n" + "added: 244[0]: 2\n" + "added: 244[1]: 4\n", + RunUn()); +} + +TEST_F(ComparisonTest, DifferentSizedUnknownFieldTest) { + unknown1_->AddVarint(240, 1); + unknown1_->AddVarint(240, 3); + unknown1_->AddVarint(240, 4); + unknown2_->AddVarint(240, 2); + unknown2_->AddVarint(240, 3); + unknown2_->AddVarint(240, 2); + unknown2_->AddVarint(240, 5); + + EXPECT_EQ( + "modified: 240[0]: 1 -> 2\n" + "modified: 240[2]: 4 -> 2\n" + "added: 240[3]: 5\n", + RunUn()); +} + +TEST_F(ComparisonTest, UnknownFieldsAll) { + unknown1_->AddVarint(243, 122); + unknown1_->AddFixed64(244, 0x0172356); + unknown1_->AddFixed64(244, 0x098); + unknown1_->AddGroup(245)->AddFixed32(248, 1); + unknown1_->mutable_field(3)->mutable_group()->AddFixed32(248, 2); + unknown1_->AddGroup(249)->AddFixed64(250, 1); + + unknown2_->AddVarint(243, 121); + unknown2_->AddLengthDelimited(73882, "test 123"); + unknown2_->AddGroup(245)->AddFixed32(248, 3); + unknown2_->AddGroup(247); + + EXPECT_EQ( + "modified: 243[0]: 122 -> 121\n" + "deleted: 244[0]: 0x0000000000172356\n" + "deleted: 244[1]: 0x0000000000000098\n" + "modified: 245[0].248[0]: 0x00000001 -> 0x00000003\n" + "deleted: 245[0].248[1]: 0x00000002\n" + "added: 247[0]: { ... }\n" + "deleted: 249[0]: { ... }\n" + "added: 73882[0]: \"test 123\"\n", + RunUn()); +} + +TEST_F(ComparisonTest, EquivalentIgnoresUnknown) { + unittest::ForeignMessage message1, message2; + + message1.set_c(5); + message1.mutable_unknown_fields()->AddVarint(123, 456); + message2.set_c(5); + message2.mutable_unknown_fields()->AddVarint(321, 654); + + EXPECT_FALSE(util::MessageDifferencer::Equals(message1, message2)); + EXPECT_TRUE(util::MessageDifferencer::Equivalent(message1, message2)); +} + +class MatchingTest : public testing::Test { + public: + typedef util::MessageDifferencer MessageDifferencer; + + protected: + MatchingTest() { + } + + ~MatchingTest() { + } + + string RunWithResult(MessageDifferencer* differencer, + const Message& msg1, const Message& msg2, + bool result) { + string output; + io::StringOutputStream output_stream(&output); + MessageDifferencer::StreamReporter reporter(&output_stream); + reporter.set_report_modified_aggregates(true); + differencer->set_report_matches(true); + differencer->ReportDifferencesTo(&reporter); + if (result) { + EXPECT_TRUE(differencer->Compare(msg1, msg2)); + } else { + EXPECT_FALSE(differencer->Compare(msg1, msg2)); + } + return output; + } + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MatchingTest); +}; + +TEST_F(MatchingTest, StreamReporterMatching) { + protobuf_unittest::TestField msg1, msg2; + msg1.set_c(72); + msg2.set_c(72); + msg1.add_rc(13); + msg2.add_rc(13); + msg1.add_rc(17); + msg2.add_rc(17); + string output; + MessageDifferencer differencer; + differencer.set_report_matches(true); + differencer.ReportDifferencesToString(&output); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + EXPECT_EQ( + "matched: c : 72\n" + "matched: rc[0] : 13\n" + "matched: rc[1] : 17\n", + output); +} + +TEST_F(MatchingTest, DontReportMatchedWhenIgnoring) { + protobuf_unittest::TestField msg1, msg2; + msg1.set_c(72); + msg2.set_c(72); + msg1.add_rc(13); + msg2.add_rc(13); + msg1.add_rc(17); + msg2.add_rc(17); + string output; + MessageDifferencer differencer; + differencer.set_report_matches(true); + differencer.ReportDifferencesToString(&output); + + differencer.IgnoreField(msg1.GetDescriptor()->FindFieldByName("c")); + + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + EXPECT_EQ( + "ignored: c\n" + "matched: rc[0] : 13\n" + "matched: rc[1] : 17\n", + output); +} + +TEST_F(MatchingTest, ReportMatchedForMovedFields) { + protobuf_unittest::TestDiffMessage msg1, msg2; + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + item->set_a(53); + item->set_b("hello"); + item = msg2.add_item(); + item->set_a(27); + item = msg2.add_item(); + item->set_a(53); + item->set_b("hello"); + item = msg1.add_item(); + item->set_a(27); + MessageDifferencer differencer; + const FieldDescriptor* desc; + desc = msg1.GetDescriptor()->FindFieldByName("item"); + differencer.TreatAsSet(desc); + + EXPECT_EQ( + "matched: item[0].a -> item[1].a : 53\n" + "matched: item[0].b -> item[1].b : \"hello\"\n" + "moved: item[0] -> item[1] : { a: 53 b: \"hello\" }\n" + "matched: item[1].a -> item[0].a : 27\n" + "moved: item[1] -> item[0] : { a: 27 }\n", + RunWithResult(&differencer, msg1, msg2, true)); +} + +TEST_F(MatchingTest, MatchesAppearInPostTraversalOrderForMovedFields) { + protobuf_unittest::TestDiffMessage msg1, msg2; + protobuf_unittest::TestDiffMessage::Item* item; + protobuf_unittest::TestField* field; + + const FieldDescriptor* desc; + const FieldDescriptor* nested_desc; + const FieldDescriptor* double_nested_desc; + desc = msg1.GetDescriptor()->FindFieldByName("item"); + nested_desc = desc->message_type()->FindFieldByName("rm"); + double_nested_desc = nested_desc->message_type()->FindFieldByName("rc"); + MessageDifferencer differencer; + differencer.TreatAsSet(desc); + differencer.TreatAsSet(nested_desc); + differencer.TreatAsSet(double_nested_desc); + + item = msg1.add_item(); + field = item->add_rm(); + field->set_c(1); + field->add_rc(2); + field->add_rc(3); + field = item->add_rm(); + field->set_c(4); + field->add_rc(5); + field->add_rc(6); + field->add_rc(7); + item = msg2.add_item(); + field = item->add_rm(); + field->set_c(4); + field->add_rc(7); + field->add_rc(6); + field->add_rc(5); + field = item->add_rm(); + field->set_c(1); + field->add_rc(3); + field->add_rc(2); + item = msg1.add_item(); + field = item->add_rm(); + field->set_c(8); + field->add_rc(10); + field->add_rc(11); + field->add_rc(9); + item = msg2.add_item(); + field = item->add_rm(); + field->set_c(8); + field->add_rc(9); + field->add_rc(10); + field->add_rc(11); + + EXPECT_EQ( + "matched: item[0].rm[0].c -> item[0].rm[1].c : 1\n" + "moved: item[0].rm[0].rc[0] -> item[0].rm[1].rc[1] : 2\n" + "moved: item[0].rm[0].rc[1] -> item[0].rm[1].rc[0] : 3\n" + "moved: item[0].rm[0] -> item[0].rm[1] : { c: 1 rc: 2 rc: 3 }\n" + "matched: item[0].rm[1].c -> item[0].rm[0].c : 4\n" + "moved: item[0].rm[1].rc[0] -> item[0].rm[0].rc[2] : 5\n" + "matched: item[0].rm[1].rc[1] -> item[0].rm[0].rc[1] : 6\n" + "moved: item[0].rm[1].rc[2] -> item[0].rm[0].rc[0] : 7\n" + "moved: item[0].rm[1] -> item[0].rm[0] : { c: 4 rc: 5 rc: 6 rc: 7 }\n" + "matched: item[0] : { rm { c: 1 rc: 2 rc: 3 }" + " rm { c: 4 rc: 5 rc: 6 rc: 7 } }\n" + "matched: item[1].rm[0].c : 8\n" + "moved: item[1].rm[0].rc[0] -> item[1].rm[0].rc[1] : 10\n" + "moved: item[1].rm[0].rc[1] -> item[1].rm[0].rc[2] : 11\n" + "moved: item[1].rm[0].rc[2] -> item[1].rm[0].rc[0] : 9\n" + "matched: item[1].rm[0] : { c: 8 rc: 10 rc: 11 rc: 9 }\n" + "matched: item[1] : { rm { c: 8 rc: 10 rc: 11 rc: 9 } }\n", + RunWithResult(&differencer, msg1, msg2, true)); +} + +TEST_F(MatchingTest, MatchAndModifiedInterleaveProperly) { + protobuf_unittest::TestDiffMessage msg1, msg2; + protobuf_unittest::TestDiffMessage::Item* item; + protobuf_unittest::TestField* field; + + const FieldDescriptor* desc; + const FieldDescriptor* nested_key; + const FieldDescriptor* nested_desc; + const FieldDescriptor* double_nested_key; + const FieldDescriptor* double_nested_desc; + desc = msg1.GetDescriptor()->FindFieldByName("item"); + nested_key = desc->message_type()->FindFieldByName("a"); + nested_desc = desc->message_type()->FindFieldByName("rm"); + double_nested_key = nested_desc->message_type()->FindFieldByName("c"); + double_nested_desc = nested_desc->message_type()->FindFieldByName("rc"); + + MessageDifferencer differencer; + differencer.TreatAsMap(desc, nested_key); + differencer.TreatAsMap(nested_desc, double_nested_key); + differencer.TreatAsSet(double_nested_desc); + + item = msg1.add_item(); + item->set_a(1); + field = item->add_rm(); + field->set_c(2); + field->add_rc(3); + field->add_rc(4); + field = item->add_rm(); + field->set_c(5); + field->add_rc(6); + field->add_rc(7); + field->add_rc(8); + item = msg1.add_item(); + item->set_a(9); + field = item->add_rm(); + field->set_c(10); + field->add_rc(11); + field->add_rc(12); + field = item->add_rm(); + field->set_c(13); + + item = msg2.add_item(); + item->set_a(1); + field = item->add_rm(); + field->set_c(5); + field->add_rc(8); + field->add_rc(8); + field->add_rc(6); + field = item->add_rm(); + field->set_c(3); + field->add_rc(2); + field->add_rc(4); + item = msg2.add_item(); + item->set_a(9); + field = item->add_rm(); + field->set_c(10); + field->add_rc(12); + field->add_rc(11); + field = item->add_rm(); + field->set_c(13); + + EXPECT_EQ( + "matched: item[0].a : 1\n" + "matched: item[0].rm[1].c -> item[0].rm[0].c : 5\n" + "moved: item[0].rm[1].rc[0] -> item[0].rm[0].rc[2] : 6\n" + "moved: item[0].rm[1].rc[2] -> item[0].rm[0].rc[0] : 8\n" + "added: item[0].rm[0].rc[1]: 8\n" + "deleted: item[0].rm[1].rc[1]: 7\n" + "modified: item[0].rm[1] -> item[0].rm[0]: { c: 5 rc: 6 rc: 7 rc: 8 } ->" + " { c: 5 rc: 8 rc: 8 rc: 6 }\n" + "added: item[0].rm[1]: { c: 3 rc: 2 rc: 4 }\n" + "deleted: item[0].rm[0]: { c: 2 rc: 3 rc: 4 }\n" + "modified: item[0]: { a: 1 rm { c: 2 rc: 3 rc: 4 }" + " rm { c: 5 rc: 6 rc: 7 rc: 8 } } ->" + " { a: 1 rm { c: 5 rc: 8 rc: 8 rc: 6 }" + " rm { c: 3 rc: 2 rc: 4 } }\n" + "matched: item[1].a : 9\n" + "matched: item[1].rm[0].c : 10\n" + "moved: item[1].rm[0].rc[0] -> item[1].rm[0].rc[1] : 11\n" + "moved: item[1].rm[0].rc[1] -> item[1].rm[0].rc[0] : 12\n" + "matched: item[1].rm[0] : { c: 10 rc: 11 rc: 12 }\n" + "matched: item[1].rm[1].c : 13\n" + "matched: item[1].rm[1] : { c: 13 }\n" + "matched: item[1] : { a: 9 rm { c: 10 rc: 11 rc: 12 } rm { c: 13 } }\n", + RunWithResult(&differencer, msg1, msg2, false)); +} + +TEST_F(MatchingTest, MatchingWorksWithExtensions) { + protobuf_unittest::TestAllExtensions msg1, msg2; + protobuf_unittest::TestAllTypes::NestedMessage* nested; + using protobuf_unittest::repeated_nested_message_extension; + + const FileDescriptor* descriptor; + const FieldDescriptor* desc; + const FieldDescriptor* nested_key; + descriptor = msg1.GetDescriptor()->file(); + desc = descriptor->FindExtensionByName("repeated_nested_message_extension"); + ASSERT_FALSE(desc == NULL); + nested_key = desc->message_type()->FindFieldByName("bb"); + + MessageDifferencer differencer; + differencer.TreatAsMap(desc, nested_key); + + nested = msg1.AddExtension(repeated_nested_message_extension); + nested->set_bb(7); + nested = msg1.AddExtension(repeated_nested_message_extension); + nested->set_bb(13); + nested = msg1.AddExtension(repeated_nested_message_extension); + nested->set_bb(11); + nested = msg2.AddExtension(repeated_nested_message_extension); + nested->set_bb(11); + nested = msg2.AddExtension(repeated_nested_message_extension); + nested->set_bb(13); + nested = msg2.AddExtension(repeated_nested_message_extension); + nested->set_bb(7); + + EXPECT_EQ( + "matched: (protobuf_unittest.repeated_nested_message_extension)[0].bb ->" + " (protobuf_unittest.repeated_nested_message_extension)[2].bb : 7\n" + "moved: (protobuf_unittest.repeated_nested_message_extension)[0] ->" + " (protobuf_unittest.repeated_nested_message_extension)[2] :" + " { bb: 7 }\n" + "matched: (protobuf_unittest.repeated_nested_message_extension)[1].bb :" + " 13\n" + "matched: (protobuf_unittest.repeated_nested_message_extension)[1] :" + " { bb: 13 }\n" + "matched: (protobuf_unittest.repeated_nested_message_extension)[2].bb ->" + " (protobuf_unittest.repeated_nested_message_extension)[0].bb :" + " 11\n" + "moved: (protobuf_unittest.repeated_nested_message_extension)[2] ->" + " (protobuf_unittest.repeated_nested_message_extension)[0] :" + " { bb: 11 }\n", + RunWithResult(&differencer, msg1, msg2, true)); +} + +TEST(AnyTest, Simple) { + protobuf_unittest::TestField value1, value2; + value1.set_a(20); + value2.set_a(21); + + protobuf_unittest::TestAny m1, m2; + m1.mutable_any_value()->PackFrom(value1); + m2.mutable_any_value()->PackFrom(value2); + util::MessageDifferencer message_differencer; + string difference_string; + message_differencer.ReportDifferencesToString(&difference_string); + EXPECT_FALSE(message_differencer.Compare(m1, m2)); + EXPECT_EQ("modified: any_value.a: 20 -> 21\n", difference_string); +} + +TEST(Anytest, TreatAsSet) { + protobuf_unittest::TestField value1, value2; + value1.set_a(20); + value1.set_b(30); + value2.set_a(20); + value2.set_b(31); + + protobuf_unittest::TestAny m1, m2; + m1.add_repeated_any_value()->PackFrom(value1); + m1.add_repeated_any_value()->PackFrom(value2); + m2.add_repeated_any_value()->PackFrom(value2); + m2.add_repeated_any_value()->PackFrom(value1); + + util::MessageDifferencer message_differencer; + message_differencer.TreatAsSet(GetFieldDescriptor(m1, "repeated_any_value")); + EXPECT_TRUE(message_differencer.Compare(m1, m2)); +} + + +} // namespace +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/message_differencer_unittest.proto b/src/google/protobuf/util/message_differencer_unittest.proto new file mode 100644 index 00000000..698775f1 --- /dev/null +++ b/src/google/protobuf/util/message_differencer_unittest.proto @@ -0,0 +1,74 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file contains messages for testing repeated field comparison + +syntax = "proto2"; +package protobuf_unittest; + +option optimize_for = SPEED; + +message TestField { + optional int32 a = 3; + optional int32 b = 4; + optional int32 c = 1; + repeated int32 rc = 2; + optional TestField m = 5; + + extend TestDiffMessage { + optional TestField tf = 100; + } +} + +message TestDiffMessage { + repeated group Item = 1 { + optional int32 a = 2; // Test basic repeated field comparison. + optional string b = 4; // Test basic repeated field comparison. + repeated int32 ra = 3; // Test SetOfSet Comparison. + repeated string rb = 5; // Test TreatAsMap when key is repeated + optional TestField m = 6; // Test TreatAsMap when key is a message + repeated TestField rm = 7; // Test TreatAsMap when key is a repeated + // message + } + + optional int32 v = 13 [deprecated = true]; + optional string w = 14; + optional TestField m = 15; + repeated int32 rv = 11; // Test for combinations + repeated string rw = 10; // Test for combinations + repeated TestField rm = 12 [deprecated = true]; // Test for combinations + + extensions 100 to 199; +} + diff --git a/src/google/protobuf/util/type_resolver.h b/src/google/protobuf/util/type_resolver.h new file mode 100644 index 00000000..77d4416a --- /dev/null +++ b/src/google/protobuf/util/type_resolver.h @@ -0,0 +1,75 @@ +// 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_UTIL_TYPE_RESOLVER_H__ +#define GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__ + +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/status.h> + + +namespace google { +namespace protobuf { +class Type; +class Enum; +} // namespace protobuf + + +namespace protobuf { +class DescriptorPool; +namespace util { + +// Abstract interface for a type resovler. +// +// Implementations of this interface must be thread-safe. +class LIBPROTOBUF_EXPORT TypeResolver { + public: + TypeResolver() {} + virtual ~TypeResolver() {} + + // Resolves a type url for a message type. + virtual util::Status ResolveMessageType( + const string& type_url, google::protobuf::Type* message_type) = 0; + + // Resolves a type url for an enum type. + virtual util::Status ResolveEnumType(const string& type_url, + google::protobuf::Enum* enum_type) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeResolver); +}; + +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__ diff --git a/src/google/protobuf/util/type_resolver_util.cc b/src/google/protobuf/util/type_resolver_util.cc new file mode 100644 index 00000000..053a4ed7 --- /dev/null +++ b/src/google/protobuf/util/type_resolver_util.cc @@ -0,0 +1,212 @@ +// 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/util/type_resolver_util.h> + +#include <google/protobuf/type.pb.h> +#include <google/protobuf/wrappers.pb.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/util/type_resolver.h> +#include <google/protobuf/stubs/status.h> + +namespace google { +namespace protobuf { +namespace util { +namespace { +using google::protobuf::BoolValue; +using google::protobuf::Enum; +using google::protobuf::EnumValue; +using google::protobuf::Field; +using google::protobuf::Option; +using google::protobuf::Type; + +using util::Status; +using util::error::INVALID_ARGUMENT; +using util::error::NOT_FOUND; + +bool SplitTypeUrl(const string& type_url, + string* url_prefix, + string* message_name) { + size_t pos = type_url.find_last_of("/"); + if (pos == string::npos) { + return false; + } + *url_prefix = type_url.substr(0, pos); + *message_name = type_url.substr(pos + 1); + return true; +} + + +class DescriptorPoolTypeResolver : public TypeResolver { + public: + DescriptorPoolTypeResolver(const string& url_prefix, + const DescriptorPool* pool) + : url_prefix_(url_prefix), pool_(pool) { + } + + Status ResolveMessageType(const string& type_url, Type* type) { + string url_prefix, message_name; + if (!SplitTypeUrl(type_url, &url_prefix, &message_name) || + url_prefix != url_prefix_) { + return Status(INVALID_ARGUMENT, "Failed to parse type url: " + type_url); + } + if (url_prefix != url_prefix_) { + return Status(INVALID_ARGUMENT, + "Cannot resolve types from URL: " + url_prefix); + } + const Descriptor* descriptor = pool_->FindMessageTypeByName(message_name); + if (descriptor == NULL) { + return Status(NOT_FOUND, "Cannot found the type: " + message_name); + } + ConvertDescriptor(descriptor, type); + return Status(); + } + + Status ResolveEnumType(const string& type_url, Enum* enum_type) { + string url_prefix, type_name; + if (!SplitTypeUrl(type_url, &url_prefix, &type_name) || + url_prefix != url_prefix_) { + return Status(INVALID_ARGUMENT, "Failed to parse type url: " + type_url); + } + if (url_prefix != url_prefix_) { + return Status(INVALID_ARGUMENT, + "Cannot resolve types from URL: " + url_prefix); + } + const EnumDescriptor* descriptor = pool_->FindEnumTypeByName(type_name); + if (descriptor == NULL) { + return Status(NOT_FOUND, "Cannot found the type: " + type_name); + } + ConvertEnumDescriptor(descriptor, enum_type); + return Status(); + } + + private: + void ConvertDescriptor(const Descriptor* descriptor, Type* type) { + type->Clear(); + type->set_name(descriptor->full_name()); + for (int i = 0; i < descriptor->field_count(); ++i) { + const FieldDescriptor* field = descriptor->field(i); + if (field->type() == FieldDescriptor::TYPE_GROUP) { + // Group fields cannot be represented with Type. We discard them. + continue; + } + ConvertFieldDescriptor(descriptor->field(i), type->add_fields()); + } + for (int i = 0; i < descriptor->oneof_decl_count(); ++i) { + type->add_oneofs(descriptor->oneof_decl(i)->name()); + } + type->mutable_source_context()->set_file_name(descriptor->file()->name()); + ConvertMessageOptions(descriptor->options(), type->mutable_options()); + } + + void ConvertMessageOptions(const MessageOptions& options, + RepeatedPtrField<Option>* output) { + if (options.map_entry()) { + Option* option = output->Add(); + option->set_name("map_entry"); + BoolValue value; + value.set_value(true); + option->mutable_value()->PackFrom(value); + } + + // TODO(xiaofeng): Set other "options"? + } + + void ConvertFieldDescriptor(const FieldDescriptor* descriptor, Field* field) { + field->set_kind(static_cast<Field::Kind>(descriptor->type())); + switch (descriptor->label()) { + case FieldDescriptor::LABEL_OPTIONAL: + field->set_cardinality(Field::CARDINALITY_OPTIONAL); + break; + case FieldDescriptor::LABEL_REPEATED: + field->set_cardinality(Field::CARDINALITY_REPEATED); + break; + case FieldDescriptor::LABEL_REQUIRED: + field->set_cardinality(Field::CARDINALITY_REQUIRED); + break; + } + field->set_number(descriptor->number()); + field->set_name(descriptor->name()); + if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE) { + field->set_type_url(GetTypeUrl(descriptor->message_type())); + } else if (descriptor->type() == FieldDescriptor::TYPE_ENUM) { + field->set_type_url(GetTypeUrl(descriptor->enum_type())); + } + if (descriptor->containing_oneof() != NULL) { + field->set_oneof_index(descriptor->containing_oneof()->index() + 1); + } + if (descriptor->is_packed()) { + field->set_packed(true); + } + + // TODO(xiaofeng): Set other field "options"? + } + + void ConvertEnumDescriptor(const EnumDescriptor* descriptor, + Enum* enum_type) { + enum_type->Clear(); + enum_type->set_name(descriptor->full_name()); + enum_type->mutable_source_context()->set_file_name( + descriptor->file()->name()); + for (int i = 0; i < descriptor->value_count(); ++i) { + const EnumValueDescriptor* value_descriptor = descriptor->value(i); + EnumValue* value = + enum_type->mutable_enumvalue()->Add(); + value->set_name(value_descriptor->name()); + value->set_number(value_descriptor->number()); + + // TODO(xiaofeng): Set EnumValue options. + } + // TODO(xiaofeng): Set Enum "options". + } + + string GetTypeUrl(const Descriptor* descriptor) { + return url_prefix_ + "/" + descriptor->full_name(); + } + + string GetTypeUrl(const EnumDescriptor* descriptor) { + return url_prefix_ + "/" + descriptor->full_name(); + } + + string url_prefix_; + const DescriptorPool* pool_; +}; + +} // namespace + +TypeResolver* NewTypeResolverForDescriptorPool( + const string& url_prefix, const DescriptorPool* pool) { + return new DescriptorPoolTypeResolver(url_prefix, pool); +} + +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/objectivec/GPBExtensionField_PackagePrivate.h b/src/google/protobuf/util/type_resolver_util.h index 6256b9a7..c0ef3c1a 100644 --- a/objectivec/GPBExtensionField_PackagePrivate.h +++ b/src/google/protobuf/util/type_resolver_util.h @@ -28,24 +28,25 @@ // (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> +#ifndef GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_H__ +#define GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_H__ -#import "GPBExtensionField.h" +#include <string> -struct GPBExtensionDescription; +#include <google/protobuf/stubs/common.h> +namespace google { +namespace protobuf { +class DescriptorPool; +namespace util { +class TypeResolver; -@interface GPBExtensionField () +// Creates a TypeResolver that serves type information in the given descriptor +// pool. Caller takes ownership of the returned TypeResolver. +LIBPROTOBUF_EXPORT TypeResolver* NewTypeResolverForDescriptorPool( + const string& url_prefix, const DescriptorPool* pool); -- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input - extensionRegistry:(GPBExtensionRegistry *)extensionRegistry - message:(GPBMessage *)message; +} // namespace util +} // namespace protobuf -- (instancetype)initWithDescription:(struct GPBExtensionDescription *)description; - -- (size_t)computeSerializedSizeIncludingTag:(id)value; -- (void)writeValue:(id)value - includingTagToCodedOutputStream:(GPBCodedOutputStream *)output; - -- (NSComparisonResult)compareByFieldNumber:(GPBExtensionField *)other; - -@end +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_H__ diff --git a/src/google/protobuf/util/type_resolver_util_test.cc b/src/google/protobuf/util/type_resolver_util_test.cc new file mode 100644 index 00000000..74b2d0da --- /dev/null +++ b/src/google/protobuf/util/type_resolver_util_test.cc @@ -0,0 +1,338 @@ +// 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/util/type_resolver_util.h> + +#include <limits> +#include <memory> +#ifndef _SHARED_PTR_H +#include <google/protobuf/stubs/shared_ptr.h> +#endif +#include <string> +#include <vector> + +#include <google/protobuf/type.pb.h> +#include <google/protobuf/wrappers.pb.h> +#include <google/protobuf/map_unittest.pb.h> +#include <google/protobuf/test_util.h> +#include <google/protobuf/unittest.pb.h> +#include <google/protobuf/util/type_resolver.h> +#include <google/protobuf/testing/googletest.h> +#include <gtest/gtest.h> + +namespace google { +namespace protobuf { +namespace util { +namespace { +using google::protobuf::Type; +using google::protobuf::Enum; +using google::protobuf::Field; +using google::protobuf::Option; +using google::protobuf::BoolValue; + +static const char kUrlPrefix[] = "type.googleapis.com"; + +class DescriptorPoolTypeResolverTest : public testing::Test { + public: + DescriptorPoolTypeResolverTest() { + resolver_.reset(NewTypeResolverForDescriptorPool( + kUrlPrefix, DescriptorPool::generated_pool())); + } + + const Field* FindField(const Type& type, const string& name) { + for (int i = 0; i < type.fields_size(); ++i) { + const Field& field = type.fields(i); + if (field.name() == name) { + return &field; + } + } + return NULL; + } + + bool HasField(const Type& type, const string& name) { + return FindField(type, name) != NULL; + } + + bool HasField(const Type& type, Field::Cardinality cardinality, + Field::Kind kind, const string& name, int number) { + const Field* field = FindField(type, name); + if (field == NULL) { + return false; + } + return field->cardinality() == cardinality && + field->kind() == kind && field->number() == number; + } + + bool CheckFieldTypeUrl(const Type& type, const string& name, + const string& type_url) { + const Field* field = FindField(type, name); + if (field == NULL) { + return false; + } + return field->type_url() == type_url; + } + + bool FieldInOneof(const Type& type, const string& name, + const string& oneof_name) { + const Field* field = FindField(type, name); + if (field == NULL || field->oneof_index() <= 0 || + field->oneof_index() > type.oneofs_size()) { + return false; + } + return type.oneofs(field->oneof_index() - 1) == oneof_name; + } + + bool IsPacked(const Type& type, const string& name) { + const Field* field = FindField(type, name); + if (field == NULL) { + return false; + } + return field->packed(); + } + + bool EnumHasValue(const Enum& type, const string& name, int number) { + for (int i = 0; i < type.enumvalue_size(); ++i) { + if (type.enumvalue(i).name() == name && + type.enumvalue(i).number() == number) { + return true; + } + } + return false; + } + + bool HasBoolOption(const RepeatedPtrField<Option>& options, + const string& name, bool value) { + for (int i = 0; i < options.size(); ++i) { + const Option& option = options.Get(i); + if (option.name() == name) { + BoolValue bool_value; + if (option.value().UnpackTo(&bool_value) && + bool_value.value() == value) { + return true; + } + } + } + return false; + } + + string GetTypeUrl(string full_name) { + return kUrlPrefix + string("/") + full_name; + } + + template<typename T> + string GetTypeUrl() { + return GetTypeUrl(T::descriptor()->full_name()); + } + + protected: + google::protobuf::scoped_ptr<TypeResolver> resolver_; +}; + +TEST_F(DescriptorPoolTypeResolverTest, TestAllTypes) { + Type type; + ASSERT_TRUE(resolver_->ResolveMessageType( + GetTypeUrl<protobuf_unittest::TestAllTypes>(), &type).ok()); + // Check all optional fields. + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_INT32, "optional_int32", 1)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_INT64, "optional_int64", 2)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_UINT32, "optional_uint32", 3)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_UINT64, "optional_uint64", 4)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_SINT32, "optional_sint32", 5)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_SINT64, "optional_sint64", 6)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_FIXED32, "optional_fixed32", 7)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_FIXED64, "optional_fixed64", 8)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_SFIXED32, "optional_sfixed32", 9)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_SFIXED64, "optional_sfixed64", 10)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_FLOAT, "optional_float", 11)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_DOUBLE, "optional_double", 12)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_BOOL, "optional_bool", 13)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_STRING, "optional_string", 14)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_BYTES, "optional_bytes", 15)); + + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_MESSAGE, "optional_nested_message", 18)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_MESSAGE, "optional_foreign_message", 19)); + + EXPECT_TRUE(CheckFieldTypeUrl( + type, "optional_nested_message", + GetTypeUrl<protobuf_unittest::TestAllTypes::NestedMessage>())); + EXPECT_TRUE(CheckFieldTypeUrl( + type, "optional_foreign_message", + GetTypeUrl<protobuf_unittest::ForeignMessage>())); + + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_ENUM, "optional_nested_enum", 21)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_ENUM, "optional_foreign_enum", 22)); + + EXPECT_TRUE(CheckFieldTypeUrl( + type, "optional_nested_enum", + GetTypeUrl("protobuf_unittest.TestAllTypes.NestedEnum"))); + EXPECT_TRUE(CheckFieldTypeUrl( + type, "optional_foreign_enum", + GetTypeUrl("protobuf_unittest.ForeignEnum"))); + + // Check all repeated fields. + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_INT32, "repeated_int32", 31)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_INT64, "repeated_int64", 32)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_UINT32, "repeated_uint32", 33)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_UINT64, "repeated_uint64", 34)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_SINT32, "repeated_sint32", 35)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_SINT64, "repeated_sint64", 36)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_FIXED32, "repeated_fixed32", 37)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_FIXED64, "repeated_fixed64", 38)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_SFIXED32, "repeated_sfixed32", 39)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_SFIXED64, "repeated_sfixed64", 40)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_FLOAT, "repeated_float", 41)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_DOUBLE, "repeated_double", 42)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_BOOL, "repeated_bool", 43)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_STRING, "repeated_string", 44)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_BYTES, "repeated_bytes", 45)); + + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_MESSAGE, "repeated_nested_message", 48)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_MESSAGE, "repeated_foreign_message", 49)); + + EXPECT_TRUE(CheckFieldTypeUrl( + type, "repeated_nested_message", + GetTypeUrl<protobuf_unittest::TestAllTypes::NestedMessage>())); + EXPECT_TRUE(CheckFieldTypeUrl( + type, "repeated_foreign_message", + GetTypeUrl<protobuf_unittest::ForeignMessage>())); + + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_ENUM, "repeated_nested_enum", 51)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_ENUM, "repeated_foreign_enum", 52)); + + EXPECT_TRUE(CheckFieldTypeUrl( + type, "repeated_nested_enum", + GetTypeUrl("protobuf_unittest.TestAllTypes.NestedEnum"))); + EXPECT_TRUE(CheckFieldTypeUrl( + type, "repeated_foreign_enum", + GetTypeUrl("protobuf_unittest.ForeignEnum"))); + + // Groups are discarded when converting to Type. + const Descriptor* descriptor = protobuf_unittest::TestAllTypes::descriptor(); + EXPECT_TRUE(descriptor->FindFieldByName("optionalgroup") != NULL); + EXPECT_TRUE(descriptor->FindFieldByName("repeatedgroup") != NULL); + ASSERT_FALSE(HasField(type, "optionalgroup")); + ASSERT_FALSE(HasField(type, "repeatedgroup")); +} + +TEST_F(DescriptorPoolTypeResolverTest, TestPackedField) { + Type type; + ASSERT_TRUE(resolver_->ResolveMessageType( + GetTypeUrl<protobuf_unittest::TestPackedTypes>(), &type).ok()); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_INT32, "packed_int32", 90)); + EXPECT_TRUE(IsPacked(type, "packed_int32")); +} + +TEST_F(DescriptorPoolTypeResolverTest, TestOneof) { + Type type; + ASSERT_TRUE(resolver_->ResolveMessageType( + GetTypeUrl<protobuf_unittest::TestAllTypes>(), &type).ok()); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_UINT32, "oneof_uint32", 111)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_MESSAGE, "oneof_nested_message", 112)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_STRING, "oneof_string", 113)); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_OPTIONAL, + Field::TYPE_BYTES, "oneof_bytes", 114)); + EXPECT_TRUE(FieldInOneof(type, "oneof_uint32", "oneof_field")); + EXPECT_TRUE(FieldInOneof(type, "oneof_nested_message", "oneof_field")); + EXPECT_TRUE(FieldInOneof(type, "oneof_string", "oneof_field")); + EXPECT_TRUE(FieldInOneof(type, "oneof_bytes", "oneof_field")); +} + +TEST_F(DescriptorPoolTypeResolverTest, TestMap) { + Type type; + ASSERT_TRUE(resolver_->ResolveMessageType( + GetTypeUrl<protobuf_unittest::TestMap>(), &type).ok()); + EXPECT_TRUE(HasField(type, Field::CARDINALITY_REPEATED, + Field::TYPE_MESSAGE, "map_int32_int32", 1)); + EXPECT_TRUE(CheckFieldTypeUrl( + type, "map_int32_int32", + GetTypeUrl("protobuf_unittest.TestMap.MapInt32Int32Entry"))); + + ASSERT_TRUE(resolver_->ResolveMessageType( + GetTypeUrl("protobuf_unittest.TestMap.MapInt32Int32Entry"), + &type).ok()); + EXPECT_TRUE(HasBoolOption(type.options(), "map_entry", true)); +} + +TEST_F(DescriptorPoolTypeResolverTest, TestEnum) { + Enum type; + ASSERT_TRUE(resolver_->ResolveEnumType( + GetTypeUrl("protobuf_unittest.TestAllTypes.NestedEnum"), &type).ok()); + EnumHasValue(type, "FOO", 1); + EnumHasValue(type, "BAR", 2); + EnumHasValue(type, "BAZ", 3); + EnumHasValue(type, "NEG", -1); +} + +} // namespace +} // namespace util +} // namespace protobuf +} // namespace google @@ -1,5 +1,13 @@ #!/usr/bin/env bash +# Note: travis currently does not support testing more than one language so the +# .travis.yml cheats and claims to only be cpp. If they add multiple language +# support, this should probably get updated to install steps and/or +# rvm/gemfile/jdk/etc. entries rather than manually doing the work. + +# .travis.yml uses matrix.exclude to block the cases where app-get can't be +# use to install things. + build_cpp() { ./autogen.sh ./configure @@ -28,12 +36,6 @@ build_csharp() { } use_java() { - if [ `uname` != "Linux" ]; then - # It's nontrivial to programmatically install a new JDK from the command - # line on OS X, so we rely on testing on Linux for Java code. - echo "Java not tested on OS X." - exit 0 # success - fi version=$1 case "$version" in jdk6) diff --git a/update_file_lists.sh b/update_file_lists.sh new file mode 100755 index 00000000..34443456 --- /dev/null +++ b/update_file_lists.sh @@ -0,0 +1,182 @@ +#!/bin/sh + +# This script copies source file lists from src/Makefile.am to cmake files. + +get_variable_value() { + local FILENAME=$1 + local VARNAME=$2 + awk " + BEGIN { start = 0; } + /^$VARNAME =/ { start = 1; } + { if (start) { print \$0; } } + /\\\\\$/ { next; } + { start = 0; } + " $FILENAME \ + | sed "s/^$VARNAME =//" \ + | sed "s/[ \\]//g" \ + | grep -v "^\\$" \ + | grep -v "^$" \ + | LC_ALL=C sort | uniq +} + +get_header_files() { + get_variable_value $@ | grep '\.h$' +} + +get_source_files() { + get_variable_value $@ | grep "cc$" +} + +get_proto_files() { + get_variable_value $@ | grep "pb.cc$" | sed "s/pb.cc/proto/" +} + +sort_files() { + for FILE in $@; do + echo $FILE + done | LC_ALL=C sort | uniq +} + +MAKEFILE=src/Makefile.am + +[ -f "$MAKEFILE" ] || { + echo "Cannot find: $MAKEFILE" + exit 1 +} + +# Extract file lists from src/Makefile.am +GZHEADERS=$(get_variable_value $MAKEFILE GZHEADERS) +HEADERS=$(get_variable_value $MAKEFILE nobase_include_HEADERS) +PUBLIC_HEADERS=$(sort_files $GZHEADERS $HEADERS) +LIBPROTOBUF_LITE_SOURCES=$(get_source_files $MAKEFILE libprotobuf_lite_la_SOURCES) +LIBPROTOBUF_SOURCES=$(get_source_files $MAKEFILE libprotobuf_la_SOURCES) +LIBPROTOC_SOURCES=$(get_source_files $MAKEFILE libprotoc_la_SOURCES) +LITE_PROTOS=$(get_proto_files $MAKEFILE protoc_lite_outputs) +PROTOS=$(get_proto_files $MAKEFILE protoc_outputs) +WKT_PROTOS=$(get_variable_value $MAKEFILE nobase_dist_proto_DATA) +COMMON_TEST_SOURCES=$(get_source_files $MAKEFILE COMMON_TEST_SOURCES) +TEST_SOURCES=$(get_source_files $MAKEFILE protobuf_test_SOURCES) +LITE_TEST_SOURCES=$(get_source_files $MAKEFILE protobuf_lite_test_SOURCES) +TEST_PLUGIN_SOURCES=$(get_source_files $MAKEFILE test_plugin_SOURCES) + +################################################################################ +# Update cmake files. +################################################################################ + +CMAKE_DIR=cmake +EXTRACT_INCLUDES_BAT=cmake/extract_includes.bat.in +[ -d "$CMAKE_DIR" ] || { + echo "Cannot find: $CMAKE_DIR" + exit 1 +} + +[ -f "$EXTRACT_INCLUDES_BAT" ] || { + echo "Cannot find: $EXTRACT_INCLUDES_BAT" + exit 1 +} + +set_cmake_value() { + local FILENAME=$1 + local VARNAME=$2 + local PREFIX=$3 + shift + shift + shift + awk -v values="$*" -v prefix="$PREFIX" " + BEGIN { start = 0; } + /^set\\($VARNAME/ { + start = 1; + print \$0; + len = split(values, vlist, \" \"); + for (i = 1; i <= len; ++i) { + printf(\" %s%s\\n\", prefix, vlist[i]); + } + next; + } + start && /^\\)/ { + start = 0; + } + !start { + print \$0; + } + " $FILENAME > /tmp/$$ + cp /tmp/$$ $FILENAME +} + + +# Replace file lists in cmake files. +CMAKE_PREFIX="\${protobuf_source_dir}/src/" +set_cmake_value $CMAKE_DIR/libprotobuf-lite.cmake libprotobuf_lite_files $CMAKE_PREFIX $LIBPROTOBUF_LITE_SOURCES +set_cmake_value $CMAKE_DIR/libprotobuf.cmake libprotobuf_files $CMAKE_PREFIX $LIBPROTOBUF_SOURCES +set_cmake_value $CMAKE_DIR/libprotoc.cmake libprotoc_files $CMAKE_PREFIX $LIBPROTOC_SOURCES +set_cmake_value $CMAKE_DIR/tests.cmake lite_test_protos "" $LITE_PROTOS +set_cmake_value $CMAKE_DIR/tests.cmake tests_protos "" $PROTOS +set_cmake_value $CMAKE_DIR/tests.cmake common_test_files $CMAKE_PREFIX $COMMON_TEST_SOURCES +set_cmake_value $CMAKE_DIR/tests.cmake tests_files $CMAKE_PREFIX $TEST_SOURCES +set_cmake_value $CMAKE_DIR/tests.cmake lite_test_files $CMAKE_PREFIX $LITE_TEST_SOURCES + +# Generate extract_includes.bat +echo "mkdir include" > $EXTRACT_INCLUDES_BAT +for HEADER in $PUBLIC_HEADERS; do + HEADER_DIR=$(dirname $HEADER) + while [ ! "$HEADER_DIR" = "." ]; do + echo $HEADER_DIR | sed "s/\\//\\\\/g" + HEADER_DIR=$(dirname $HEADER_DIR) + done +done | sort | uniq | sed "s/^/mkdir include\\\\/" >> $EXTRACT_INCLUDES_BAT +for HEADER in $PUBLIC_HEADERS; do + WINPATH=$(echo $HEADER | sed 's;/;\\;g') + echo "copy \${PROTOBUF_SOURCE_WIN32_PATH}\\..\\src\\$WINPATH include\\$WINPATH" >> $EXTRACT_INCLUDES_BAT +done + +################################################################################ +# Update bazel BUILD files. +################################################################################ + +BAZEL_BUILD=./BUILD +[ -f "$BAZEL_BUILD" ] || { + echo "Cannot find: $BAZEL_BUILD" + exit 1 +} +set_bazel_value() { + local FILENAME=$1 + local VARNAME=$2 + local PREFIX=$3 + shift + shift + shift + awk -v values="$*" -v prefix="$PREFIX" " + BEGIN { start = 0; } + /# AUTOGEN\\($VARNAME\\)/ { + start = 1; + print \$0; + # replace \$0 with indent. + sub(/#.*/, \"\", \$0) + len = split(values, vlist, \" \"); + for (i = 1; i <= len; ++i) { + printf(\"%s\\\"%s%s\\\",\n\", \$0, prefix, vlist[i]); + } + next; + } + start && /\]/ { + start = 0 + } + !start { + print \$0; + } + " $FILENAME > /tmp/$$ + cp /tmp/$$ $FILENAME +} + + +BAZEL_PREFIX="src/" +set_bazel_value $BAZEL_BUILD protobuf_lite_srcs $BAZEL_PREFIX $LIBPROTOBUF_LITE_SOURCES +set_bazel_value $BAZEL_BUILD protobuf_srcs $BAZEL_PREFIX $LIBPROTOBUF_SOURCES +set_bazel_value $BAZEL_BUILD protoc_lib_srcs $BAZEL_PREFIX $LIBPROTOC_SOURCES +set_bazel_value $BAZEL_BUILD lite_test_protos "" $LITE_PROTOS +set_bazel_value $BAZEL_BUILD well_known_protos "" $WKT_PROTOS +set_bazel_value $BAZEL_BUILD test_protos "" $PROTOS +set_bazel_value $BAZEL_BUILD common_test_srcs $BAZEL_PREFIX $COMMON_TEST_SOURCES +set_bazel_value $BAZEL_BUILD test_srcs $BAZEL_PREFIX $TEST_SOURCES +set_bazel_value $BAZEL_BUILD test_plugin_srcs $BAZEL_PREFIX $TEST_PLUGIN_SOURCES + diff --git a/vsprojects/config.h b/vsprojects/config.h deleted file mode 100755 index a93bb033..00000000 --- a/vsprojects/config.h +++ /dev/null @@ -1,20 +0,0 @@ -/* protobuf config.h for MSVC. On other platforms, this is generated - * automatically by autoheader / autoconf / configure. */ - -#include <google/protobuf/stubs/pbconfig.h> - -#define HASH_MAP_H GOOGLE_PROTOBUF_HASH_MAP_H -#define HASH_NAMESPACE GOOGLE_PROTOBUF_HASH_NAMESPACE -#define HASH_SET_H GOOGLE_PROTOBUF_HASH_SET_H - -#ifdef GOOGLE_PROTOBUF_HAVE_HASH_MAP -#define HAVE_HASH_MAP GOOGLE_PROTOBUF_HAVE_HASH_MAP -#endif - -#ifdef GOOGLE_PROTOBUF_HAVE_HASH_SET -#define HAVE_HASH_SET GOOGLE_PROTOBUF_HAVE_HASH_SET -#endif - -/* define if you want to use zlib. See readme.txt for additional - * requirements. */ -// #define HAVE_ZLIB 1 diff --git a/vsprojects/convert2008to2005.sh b/vsprojects/convert2008to2005.sh deleted file mode 100755 index 60eccaf3..00000000 --- a/vsprojects/convert2008to2005.sh +++ /dev/null @@ -1,20 +0,0 @@ -#! /bin/sh -e - -# This script downgrades MSVC 2008 projects to MSVC 2005 projects, allowing -# people with MSVC 2005 to open them. Otherwise, MSVC 2005 simply refuses to -# open projects created with 2008. We run this as part of our release process. -# If you obtained the code direct from version control and you want to use -# MSVC 2005, you may have to run this manually. (Hint: Use Cygwin or MSYS.) - -for file in *.sln; do - echo "downgrading $file..." - sed -i -re 's/Format Version 10.00/Format Version 9.00/g; - s/Visual Studio 2008/Visual Studio 2005/g;' $file -done - -for file in *.vcproj; do - echo "downgrading $file..." - sed -i -re 's/Version="9.00"/Version="8.00"/g;' $file -done - -# Yes, really, that's it. diff --git a/vsprojects/extract_includes.bat b/vsprojects/extract_includes.bat deleted file mode 100755 index 989fef4b..00000000 --- a/vsprojects/extract_includes.bat +++ /dev/null @@ -1,102 +0,0 @@ -md include -md include\google -md include\google\protobuf -md include\google\protobuf\stubs -md include\google\protobuf\io -md include\google\protobuf\compiler -md include\google\protobuf\compiler\cpp -md include\google\protobuf\compiler\java -md include\google\protobuf\compiler\javanano -md include\google\protobuf\compiler\python -md include\google\protobuf\compiler\ruby -copy ..\src\google\protobuf\any.pb.h include\google\protobuf\any.pb.h -copy ..\src\google\protobuf\api.pb.h include\google\protobuf\api.pb.h -copy ..\src\google\protobuf\any.h include\google\protobuf\any.h -copy ..\src\google\protobuf\arena.h include\google\protobuf\arena.h -copy ..\src\google\protobuf\arenastring.h include\google\protobuf\arenastring.h -copy ..\src\google\protobuf\compiler\code_generator.h include\google\protobuf\compiler\code_generator.h -copy ..\src\google\protobuf\compiler\command_line_interface.h include\google\protobuf\compiler\command_line_interface.h -copy ..\src\google\protobuf\compiler\cpp\cpp_generator.h include\google\protobuf\compiler\cpp\cpp_generator.h -copy ..\src\google\protobuf\compiler\csharp\csharp_generator.h include\google\protobuf\compiler\csharp\csharp_generator.h -copy ..\src\google\protobuf\compiler\importer.h include\google\protobuf\compiler\importer.h -copy ..\src\google\protobuf\compiler\java\java_generator.h include\google\protobuf\compiler\java\java_generator.h -copy ..\src\google\protobuf\compiler\java\java_names.h include\google\protobuf\compiler\java\java_names.h -copy ..\src\google\protobuf\compiler\javanano\javanano_generator.h include\google\protobuf\compiler\javanano\javanano_generator.h -copy ..\src\google\protobuf\compiler\objectivec\objectivec_generator.h include\google\protobuf\compiler\objectivec\objectivec_generator.h -copy ..\src\google\protobuf\compiler\objectivec\objectivec_helpers.h include\google\protobuf\compiler\objectivec\objectivec_helpers.h -copy ..\src\google\protobuf\compiler\parser.h include\google\protobuf\compiler\parser.h -copy ..\src\google\protobuf\compiler\plugin.h include\google\protobuf\compiler\plugin.h -copy ..\src\google\protobuf\compiler\plugin.pb.h include\google\protobuf\compiler\plugin.pb.h -copy ..\src\google\protobuf\compiler\python\python_generator.h include\google\protobuf\compiler\python\python_generator.h -copy ..\src\google\protobuf\compiler\ruby\ruby_generator.h include\google\protobuf\compiler\ruby\ruby_generator.h -copy ..\src\google\protobuf\descriptor_database.h include\google\protobuf\descriptor_database.h -copy ..\src\google\protobuf\descriptor.h include\google\protobuf\descriptor.h -copy ..\src\google\protobuf\descriptor.pb.h include\google\protobuf\descriptor.pb.h -copy ..\src\google\protobuf\dynamic_message.h include\google\protobuf\dynamic_message.h -copy ..\src\google\protobuf\empty.pb.h include\google\protobuf\empty.pb.h -copy ..\src\google\protobuf\extension_set.h include\google\protobuf\extension_set.h -copy ..\src\google\protobuf\field_mask.pb.h include\google\protobuf\field_mask.pb.h -copy ..\src\google\protobuf\generated_enum_reflection.h include\google\protobuf\generated_enum_reflection.h -copy ..\src\google\protobuf\generated_enum_util.h include\google\protobuf\generated_enum_util.h -copy ..\src\google\protobuf\generated_message_reflection.h include\google\protobuf\generated_message_reflection.h -copy ..\src\google\protobuf\generated_message_util.h include\google\protobuf\generated_message_util.h -copy ..\src\google\protobuf\io\coded_stream.h include\google\protobuf\io\coded_stream.h -copy ..\src\google\protobuf\io\gzip_stream.h include\google\protobuf\io\gzip_stream.h -copy ..\src\google\protobuf\io\printer.h include\google\protobuf\io\printer.h -copy ..\src\google\protobuf\io\strtod.h include\google\protobuf\io\strtod.h -copy ..\src\google\protobuf\io\tokenizer.h include\google\protobuf\io\tokenizer.h -copy ..\src\google\protobuf\io\zero_copy_stream.h include\google\protobuf\io\zero_copy_stream.h -copy ..\src\google\protobuf\io\zero_copy_stream_impl.h include\google\protobuf\io\zero_copy_stream_impl.h -copy ..\src\google\protobuf\io\zero_copy_stream_impl_lite.h include\google\protobuf\io\zero_copy_stream_impl_lite.h -copy ..\src\google\protobuf\map_entry.h include\google\protobuf\map_entry.h -copy ..\src\google\protobuf\map_entry_lite.h include\google\protobuf\map_entry_lite.h -copy ..\src\google\protobuf\map_field.h include\google\protobuf\map_field.h -copy ..\src\google\protobuf\map_field_inl.h include\google\protobuf\map_field_inl.h -copy ..\src\google\protobuf\map_field_lite.h include\google\protobuf\map_field_lite.h -copy ..\src\google\protobuf\map.h include\google\protobuf\map.h -copy ..\src\google\protobuf\map_type_handler.h include\google\protobuf\map_type_handler.h -copy ..\src\google\protobuf\message.h include\google\protobuf\message.h -copy ..\src\google\protobuf\message_lite.h include\google\protobuf\message_lite.h -copy ..\src\google\protobuf\metadata.h include\google\protobuf\metadata.h -copy ..\src\google\protobuf\reflection.h include\google\protobuf\reflection.h -copy ..\src\google\protobuf\reflection_ops.h include\google\protobuf\reflection_ops.h -copy ..\src\google\protobuf\repeated_field.h include\google\protobuf\repeated_field.h -copy ..\src\google\protobuf\repeated_field_reflection.h include\google\protobuf\repeated_field_reflection.h -copy ..\src\google\protobuf\service.h include\google\protobuf\service.h -copy ..\src\google\protobuf\source_context.pb.h include\google\protobuf\source_context.pb.h -copy ..\src\google\protobuf\struct.pb.h include\google\protobuf\struct.pb.h -copy ..\src\google\protobuf\stubs\atomicops.h include\google\protobuf\stubs\atomicops.h -copy ..\src\google\protobuf\stubs\atomicops_internals_aix.h include\google\protobuf\stubs\atomicops_internals_aix.h -copy ..\src\google\protobuf\stubs\atomicops_internals_arm64_gcc.h include\google\protobuf\stubs\atomicops_internals_arm64_gcc.h -copy ..\src\google\protobuf\stubs\atomicops_internals_arm_gcc.h include\google\protobuf\stubs\atomicops_internals_arm_gcc.h -copy ..\src\google\protobuf\stubs\atomicops_internals_arm_qnx.h include\google\protobuf\stubs\atomicops_internals_arm_qnx.h -copy ..\src\google\protobuf\stubs\atomicops_internals_atomicword_compat.h include\google\protobuf\stubs\atomicops_internals_atomicword_compat.h -copy ..\src\google\protobuf\stubs\atomicops_internals_generic_gcc.h include\google\protobuf\stubs\atomicops_internals_generic_gcc.h -copy ..\src\google\protobuf\stubs\atomicops_internals_macosx.h include\google\protobuf\stubs\atomicops_internals_macosx.h -copy ..\src\google\protobuf\stubs\atomicops_internals_mips_gcc.h include\google\protobuf\stubs\atomicops_internals_mips_gcc.h -copy ..\src\google\protobuf\stubs\atomicops_internals_pnacl.h include\google\protobuf\stubs\atomicops_internals_pnacl.h -copy ..\src\google\protobuf\stubs\atomicops_internals_solaris.h include\google\protobuf\stubs\atomicops_internals_solaris.h -copy ..\src\google\protobuf\stubs\atomicops_internals_tsan.h include\google\protobuf\stubs\atomicops_internals_tsan.h -copy ..\src\google\protobuf\stubs\atomicops_internals_x86_gcc.h include\google\protobuf\stubs\atomicops_internals_x86_gcc.h -copy ..\src\google\protobuf\stubs\atomicops_internals_x86_msvc.h include\google\protobuf\stubs\atomicops_internals_x86_msvc.h -copy ..\src\google\protobuf\stubs\atomic_sequence_num.h include\google\protobuf\stubs\atomic_sequence_num.h -copy ..\src\google\protobuf\stubs\casts.h include\google\protobuf\stubs\casts.h -copy ..\src\google\protobuf\stubs\common.h include\google\protobuf\stubs\common.h -copy ..\src\google\protobuf\stubs\fastmem.h include\google\protobuf\stubs\fastmem.h -copy ..\src\google\protobuf\stubs\hash.h include\google\protobuf\stubs\hash.h -copy ..\src\google\protobuf\stubs\once.h include\google\protobuf\stubs\once.h -copy ..\src\google\protobuf\stubs\platform_macros.h include\google\protobuf\stubs\platform_macros.h -copy ..\src\google\protobuf\stubs\shared_ptr.h include\google\protobuf\stubs\shared_ptr.h -copy ..\src\google\protobuf\stubs\singleton.h include\google\protobuf\stubs\singleton.h -copy ..\src\google\protobuf\stubs\stl_util.h include\google\protobuf\stubs\stl_util.h -copy ..\src\google\protobuf\stubs\template_util.h include\google\protobuf\stubs\template_util.h -copy ..\src\google\protobuf\stubs\type_traits.h include\google\protobuf\stubs\type_traits.h -copy ..\src\google\protobuf\text_format.h include\google\protobuf\text_format.h -copy ..\src\google\protobuf\timestamp.pb.h include\google\protobuf\timestamp.pb.h -copy ..\src\google\protobuf\type.pb.h include\google\protobuf\type.pb.h -copy ..\src\google\protobuf\unknown_field_set.h include\google\protobuf\unknown_field_set.h -copy ..\src\google\protobuf\wire_format.h include\google\protobuf\wire_format.h -copy ..\src\google\protobuf\wire_format_lite.h include\google\protobuf\wire_format_lite.h -copy ..\src\google\protobuf\wire_format_lite_inl.h include\google\protobuf\wire_format_lite_inl.h -copy ..\src\google\protobuf\wrappers.pb.h include\google\protobuf\wrappers.pb.h -copy google\protobuf\stubs\pbconfig.h include\google\protobuf\stubs\pbconfig.h diff --git a/vsprojects/google/protobuf/stubs/pbconfig.h b/vsprojects/google/protobuf/stubs/pbconfig.h deleted file mode 100755 index 9629f2e4..00000000 --- a/vsprojects/google/protobuf/stubs/pbconfig.h +++ /dev/null @@ -1,49 +0,0 @@ -/* protobuf config.h for MSVC. On other platforms, this is generated - * automatically by autoheader / autoconf / configure. */ - -// NOTE: if you add new macros in this file manually, please propagate the macro -// to vsprojects/config.h. - -/* the namespace of hash_map/hash_set */ -// Apparently Microsoft decided to move hash_map *back* to the std namespace -// in MSVC 2010: -// http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx -// And.. they are moved back to stdext in MSVC 2013 (haven't checked 2012). That -// said, use unordered_map for MSVC 2010 and beyond is our safest bet. -#if _MSC_VER >= 1600 // Since Visual Studio 2010 -#define GOOGLE_PROTOBUF_HASH_NAMESPACE std -#define GOOGLE_PROTOBUF_HASH_MAP_H <unordered_map> -#define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map -#define GOOGLE_PROTOBUF_HASH_SET_H <unordered_set> -#define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set -#define GOOGLE_PROTOBUF_HASH_COMPARE std::hash_compare -#elif _MSC_VER >= 1500 // Since Visual Studio 2008 -#define GOOGLE_PROTOBUF_HASH_NAMESPACE std::tr1 -#define GOOGLE_PROTOBUF_HASH_MAP_H <unordered_map> -#define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map -#define GOOGLE_PROTOBUF_HASH_SET_H <unordered_set> -#define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set -#define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare -#elif _MSC_VER >= 1310 -#define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext -#define GOOGLE_PROTOBUF_HASH_MAP_H <hash_map> -#define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map -#define GOOGLE_PROTOBUF_HASH_SET_H <hash_set> -#define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set -#define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare -#else -#define GOOGLE_PROTOBUF_HASH_NAMESPACE std -#define GOOGLE_PROTOBUF_HASH_MAP_H <hash_map> -#define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map -#define GOOGLE_PROTOBUF_HASH_SET_H <hash_set> -#define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set -#define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare -#endif - -/* the location of <hash_set> */ - -/* define if the compiler has hash_map */ -#define GOOGLE_PROTOBUF_HAVE_HASH_MAP 1 - -/* define if the compiler has hash_set */ -#define GOOGLE_PROTOBUF_HAVE_HASH_SET 1 diff --git a/vsprojects/libprotobuf-lite.vcproj b/vsprojects/libprotobuf-lite.vcproj deleted file mode 100644 index be20dd0b..00000000 --- a/vsprojects/libprotobuf-lite.vcproj +++ /dev/null @@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="libprotobuf-lite" - ProjectGUID="{49EA010D-706F-4BE2-A397-77854B72A040}" - Keyword="Win32Proj" - TargetFrameworkVersion="0" - > - <Platforms> - <Platform - Name="Win32" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="$(OutDir)\$(ProjectName)" - ConfigurationType="4" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305" - Optimization="0" - AdditionalIncludeDirectories="../src;." - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBPROTOBUF_EXPORTS;" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="3" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="4" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="$(OutDir)\$(ProjectName)" - ConfigurationType="4" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305" - AdditionalIncludeDirectories="../src;." - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBPROTOBUF_EXPORTS;" - RuntimeLibrary="2" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="Header Files" - Filter="h;hpp;hxx;hm;inl;inc;xsd" - UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" - > - <File RelativePath=".\config.h"></File> - <File RelativePath=".\google\protobuf\stubs\pbconfig.h"></File> - <File RelativePath="..\src\google\protobuf\extension_set.h"></File> - <File RelativePath="..\src\google\protobuf\generated_message_util.h"></File> - <File RelativePath="..\src\google\protobuf\generated_enum_util.h"></File> - <File RelativePath="..\src\google\protobuf\io\coded_stream.h"></File> - <File RelativePath="..\src\google\protobuf\io\zero_copy_stream.h"></File> - <File RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl_lite.h"></File> - <File RelativePath="..\src\google\protobuf\map_entry_lite.h"></File> - <File RelativePath="..\src\google\protobuf\map_field_lite.h"></File> - <File RelativePath="..\src\google\protobuf\message_lite.h"></File> - <File RelativePath="..\src\google\protobuf\repeated_field.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\atomicops.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\atomicops_internals_x86_msvc.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\common.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\once.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\platform_macros.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\stl_util.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\template_util.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\type_traits.h"></File> - <File RelativePath="..\src\google\protobuf\wire_format_lite.h"></File> - <File RelativePath="..\src\google\protobuf\wire_format_lite_inl.h"></File> - </Filter> - <Filter - Name="Resource Files" - Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" - UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" - > - </Filter> - <Filter - Name="Source Files" - Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" - UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" - > - <File RelativePath="..\src\google\protobuf\arena.cc"></File> - <File RelativePath="..\src\google\protobuf\arenastring.cc"></File> - <File RelativePath="..\src\google\protobuf\extension_set.cc"></File> - <File RelativePath="..\src\google\protobuf\generated_message_util.cc"></File> - <File RelativePath="..\src\google\protobuf\io\coded_stream.cc"></File> - <File RelativePath="..\src\google\protobuf\io\coded_stream_inl.h"></File> - <File RelativePath="..\src\google\protobuf\io\zero_copy_stream.cc"></File> - <File RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl_lite.cc"></File> - <File RelativePath="..\src\google\protobuf\message_lite.cc"></File> - <File RelativePath="..\src\google\protobuf\repeated_field.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\atomicops_internals_x86_gcc.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\atomicops_internals_x86_msvc.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\common.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\hash.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\map_util.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\once.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\shared_ptr.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\stringprintf.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\stringprintf.h"></File> - <File RelativePath="..\src\google\protobuf\wire_format_lite.cc"></File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/vsprojects/libprotobuf.vcproj b/vsprojects/libprotobuf.vcproj deleted file mode 100644 index 0daec6d9..00000000 --- a/vsprojects/libprotobuf.vcproj +++ /dev/null @@ -1,266 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="libprotobuf" - ProjectGUID="{3E283F37-A4ED-41B7-A3E6-A2D89D131A30}" - Keyword="Win32Proj" - TargetFrameworkVersion="0" - > - <Platforms> - <Platform - Name="Win32" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="$(OutDir)\$(ProjectName)" - ConfigurationType="4" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305" - Optimization="0" - AdditionalIncludeDirectories="../src;." - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBPROTOBUF_EXPORTS;" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="3" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="4" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="$(OutDir)\$(ProjectName)" - ConfigurationType="4" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305" - AdditionalIncludeDirectories="../src;." - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBPROTOBUF_EXPORTS;" - RuntimeLibrary="2" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="Header Files" - Filter="h;hpp;hxx;hm;inl;inc;xsd" - UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" - > - <File RelativePath=".\config.h"></File> - <File RelativePath=".\google\protobuf\stubs\pbconfig.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\importer.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\parser.h"></File> - <File RelativePath="..\src\google\protobuf\descriptor.h"></File> - <File RelativePath="..\src\google\protobuf\descriptor.pb.h"></File> - <File RelativePath="..\src\google\protobuf\descriptor_database.h"></File> - <File RelativePath="..\src\google\protobuf\dynamic_message.h"></File> - <File RelativePath="..\src\google\protobuf\extension_set.h"></File> - <File RelativePath="..\src\google\protobuf\generated_enum_util.h"></File> - <File RelativePath="..\src\google\protobuf\generated_message_reflection.h"></File> - <File RelativePath="..\src\google\protobuf\generated_message_util.h"></File> - <File RelativePath="..\src\google\protobuf\io\coded_stream.h"></File> - <File RelativePath="..\src\google\protobuf\io\gzip_stream.h"></File> - <File RelativePath="..\src\google\protobuf\io\strtod.h"></File> - <File RelativePath="..\src\google\protobuf\io\printer.h"></File> - <File RelativePath="..\src\google\protobuf\io\tokenizer.h"></File> - <File RelativePath="..\src\google\protobuf\io\zero_copy_stream.h"></File> - <File RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl.h"></File> - <File RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl_lite.h"></File> - <File RelativePath="..\src\google\protobuf\map_entry_lite.h"></File> - <File RelativePath="..\src\google\protobuf\map_field_lite.h"></File> - <File RelativePath="..\src\google\protobuf\message.h"></File> - <File RelativePath="..\src\google\protobuf\message_lite.h"></File> - <File RelativePath="..\src\google\protobuf\reflection_ops.h"></File> - <File RelativePath="..\src\google\protobuf\repeated_field.h"></File> - <File RelativePath="..\src\google\protobuf\service.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\atomicops.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\atomicops_internals_x86_msvc.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\common.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\map_util.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\once.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\platform_macros.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\stl_util.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\strutil.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\substitute.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\template_util.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\type_traits.h"></File> - <File RelativePath="..\src\google\protobuf\text_format.h"></File> - <File RelativePath="..\src\google\protobuf\unknown_field_set.h"></File> - <File RelativePath="..\src\google\protobuf\wire_format.h"></File> - <File RelativePath="..\src\google\protobuf\wire_format_lite.h"></File> - <File RelativePath="..\src\google\protobuf\wire_format_lite_inl.h"></File> - </Filter> - <Filter - Name="Resource Files" - Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" - UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" - > - </Filter> - <Filter - Name="Source Files" - Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" - UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" - > - <File RelativePath="..\src\google\protobuf\arena.cc"></File> - <File RelativePath="..\src\google\protobuf\arenastring.cc"></File> - <File RelativePath="..\src\google\protobuf\extension_set.cc"></File> - <File RelativePath="..\src\google\protobuf\generated_message_util.cc"></File> - <File RelativePath="..\src\google\protobuf\io\coded_stream.cc"></File> - <File RelativePath="..\src\google\protobuf\io\coded_stream_inl.h"></File> - <File RelativePath="..\src\google\protobuf\io\zero_copy_stream.cc"></File> - <File RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl_lite.cc"></File> - <File RelativePath="..\src\google\protobuf\message_lite.cc"></File> - <File RelativePath="..\src\google\protobuf\repeated_field.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\atomicops_internals_x86_gcc.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\atomicops_internals_x86_msvc.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\common.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\hash.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\map_util.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\once.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\shared_ptr.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\stringprintf.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\stringprintf.h"></File> - <File RelativePath="..\src\google\protobuf\wire_format_lite.cc"></File> - <File RelativePath="..\src\google\protobuf\any.pb.cc"></File> - <File RelativePath="..\src\google\protobuf\any.cc"></File> - <File RelativePath="..\src\google\protobuf\api.pb.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\importer.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\parser.cc"></File> - <File RelativePath="..\src\google\protobuf\descriptor.cc"></File> - <File RelativePath="..\src\google\protobuf\descriptor_database.cc"></File> - <File RelativePath="..\src\google\protobuf\descriptor.pb.cc"></File> - <File RelativePath="..\src\google\protobuf\duration.pb.cc"></File> - <File RelativePath="..\src\google\protobuf\dynamic_message.cc"></File> - <File RelativePath="..\src\google\protobuf\empty.pb.cc"></File> - <File RelativePath="..\src\google\protobuf\extension_set_heavy.cc"></File> - <File RelativePath="..\src\google\protobuf\field_mask.pb.cc"></File> - <File RelativePath="..\src\google\protobuf\generated_message_reflection.cc"></File> - <File RelativePath="..\src\google\protobuf\io\gzip_stream.cc"></File> - <File RelativePath="..\src\google\protobuf\io\printer.cc"></File> - <File RelativePath="..\src\google\protobuf\io\strtod.cc"></File> - <File RelativePath="..\src\google\protobuf\io\tokenizer.cc"></File> - <File RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl.cc"></File> - <File RelativePath="..\src\google\protobuf\map_field.cc"></File> - <File RelativePath="..\src\google\protobuf\message.cc"></File> - <File RelativePath="..\src\google\protobuf\reflection_internal.h"></File> - <File RelativePath="..\src\google\protobuf\reflection_ops.cc"></File> - <File RelativePath="..\src\google\protobuf\service.cc"></File> - <File RelativePath="..\src\google\protobuf\source_context.pb.cc"></File> - <File RelativePath="..\src\google\protobuf\struct.pb.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\structurally_valid.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\strutil.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\strutil.h"></File> - <File RelativePath="..\src\google\protobuf\stubs\substitute.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\substitute.h"></File> - <File RelativePath="..\src\google\protobuf\text_format.cc"></File> - <File RelativePath="..\src\google\protobuf\type.pb.cc"></File> - <File RelativePath="..\src\google\protobuf\timestamp.pb.cc"></File> - <File RelativePath="..\src\google\protobuf\unknown_field_set.cc"></File> - <File RelativePath="..\src\google\protobuf\wire_format.cc"></File> - <File RelativePath="..\src\google\protobuf\wrappers.pb.cc"></File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/vsprojects/libprotoc.vcproj b/vsprojects/libprotoc.vcproj deleted file mode 100644 index 515a6096..00000000 --- a/vsprojects/libprotoc.vcproj +++ /dev/null @@ -1,342 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="libprotoc" - ProjectGUID="{B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}" - Keyword="Win32Proj" - TargetFrameworkVersion="0" - > - <Platforms> - <Platform - Name="Win32" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="$(OutDir)\$(ProjectName)" - ConfigurationType="4" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305" - Optimization="0" - AdditionalIncludeDirectories="../src;." - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBPROTOC_EXPORTS;" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="3" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="4" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="$(OutDir)\$(ProjectName)" - ConfigurationType="4" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305" - AdditionalIncludeDirectories="../src;." - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBPROTOC_EXPORTS;" - RuntimeLibrary="2" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="Header Files" - Filter="h;hpp;hxx;hm;inl;inc;xsd" - UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" - > - <File RelativePath="..\src\google\protobuf\compiler\code_generator.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\command_line_interface.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\subprocess.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\zip_writer.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\plugin.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\plugin.pb.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_extension.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_file.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_generator.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_helpers.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_map_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_options.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_primitive_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_service.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_string_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_enum.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_enum_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_extension.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_field_base.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_generator.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_helpers.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_message.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_message_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_primitive_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_repeated_enum_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_repeated_message_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_repeated_primitive_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_source_generator_base.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_umbrella_class.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_writer.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_context.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_enum.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_enum_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_enum_field_lite.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_extension.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_file.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_generator.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_generator_factory.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_helpers.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_lazy_message_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_lazy_message_field_lite.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_map_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_map_field_lite.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_message.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_message_lite.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_message_builder.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_message_builder_lite.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_message_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_message_field_lite.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_name_resolver.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_primitive_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_primitive_field_lite.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_service.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_shared_code_generator.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_string_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_string_field_lite.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_enum_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_enum.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_extension.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_file.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_generator.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_helpers.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_map_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_message_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_message.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_params.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_primitive_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_enum.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_enum_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_extension.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_file.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_generator.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_helpers.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_map_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_message.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_message_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_oneof.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_primitive_field.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\python\python_generator.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\ruby\ruby_generator.h"></File> - </Filter> - <Filter - Name="Resource Files" - Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" - UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" - > - </Filter> - <Filter - Name="Source Files" - Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" - UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" - > - <File RelativePath="..\src\google\protobuf\compiler\code_generator.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\command_line_interface.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\plugin.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\plugin.pb.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\subprocess.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\zip_writer.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_extension.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_file.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_generator.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_helpers.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_map_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_primitive_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_service.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_string_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_enum.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_enum_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_extension.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_field_base.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_generator.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_helpers.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_message.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_message_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_primitive_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_repeated_enum_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_repeated_message_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_repeated_primitive_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_source_generator_base.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_umbrella_class.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_writer.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_context.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_enum.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_enum_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_enum_field_lite.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_extension.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_file.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_generator.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_generator_factory.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_helpers.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_lazy_message_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_lazy_message_field_lite.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_map_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_map_field_lite.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_message.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_message_lite.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_message_builder.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_message_builder_lite.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_message_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_message_field_lite.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_name_resolver.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_primitive_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_primitive_field_lite.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_service.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_shared_code_generator.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_string_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_string_field_lite.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_enum.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_enum_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_extension.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_file.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_generator.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_helpers.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_map_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_message.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_message_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_primitive_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_enum.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_enum_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_extension.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_file.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_generator.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_helpers.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_map_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_message.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_message_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_oneof.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_primitive_field.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\python\python_generator.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\ruby\ruby_generator.cc"></File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/vsprojects/lite-test.vcproj b/vsprojects/lite-test.vcproj deleted file mode 100644 index aba212b1..00000000 --- a/vsprojects/lite-test.vcproj +++ /dev/null @@ -1,332 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="lite-test" - ProjectGUID="{12015ACE-42BE-4952-A5A0-44A9A46908E2}" - RootNamespace="tests" - Keyword="Win32Proj" - TargetFrameworkVersion="0" - > - <Platforms> - <Platform - Name="Win32" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="$(OutDir)\$(ProjectName)" - ConfigurationType="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - Description="" - CommandLine="" - AdditionalDependencies="" - Outputs="" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305" - Optimization="0" - AdditionalIncludeDirectories="../src;.;../gtest/include" - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_VARIADIC_MAX=10;" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="3" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="4" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - LinkIncremental="2" - GenerateDebugInformation="true" - SubSystem="1" - TargetMachine="1" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCManifestTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCAppVerifierTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="$(OutDir)\$(ProjectName)" - ConfigurationType="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - Description="" - CommandLine="" - AdditionalDependencies="" - Outputs="" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305" - AdditionalIncludeDirectories="../src;.;../gtest/include" - PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_VARIADIC_MAX=10;" - RuntimeLibrary="2" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - LinkIncremental="2" - GenerateDebugInformation="true" - SubSystem="1" - OptimizeReferences="2" - EnableCOMDATFolding="2" - TargetMachine="1" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCManifestTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCAppVerifierTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="Header Files" - Filter="h;hpp;hxx;hm;inl;inc;xsd" - UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" - > - <File RelativePath=".\google\protobuf\map_lite_unittest.pb.h"></File> - <File RelativePath=".\google\protobuf\unittest_import_lite.pb.h"></File> - <File RelativePath=".\google\protobuf\unittest_import_public_lite.pb.h"></File> - <File RelativePath=".\google\protobuf\unittest_lite.pb.h"></File> - <File RelativePath="..\src\google\protobuf\arena_test_util.h"></File> - <File RelativePath="..\src\google\protobuf\map_lite_test_util.h"></File> - <File RelativePath="..\src\google\protobuf\test_util_lite.h"></File> - </Filter> - <Filter - Name="Resource Files" - Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" - UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" - > - </Filter> - <Filter - Name="Source Files" - Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" - UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" - > - <File RelativePath=".\google\protobuf\map_lite_unittest.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_import_lite.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_import_public_lite.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_lite.pb.cc"></File> - <File RelativePath="..\src\google\protobuf\arena_test_util.cc"></File> - <File RelativePath="..\src\google\protobuf\lite_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\map_lite_test_util.cc"></File> - <File RelativePath="..\src\google\protobuf\test_util_lite.cc"></File> - </Filter> - <File - RelativePath="..\src\google\protobuf\map_lite_unittest.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating map_lite_unittest.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/map_lite_unittest.proto
" - Outputs="google\protobuf\map_lite_unittest.pb.h;google\protobuf\map_lite_unittest.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating map_lite_unittest.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/map_lite_unittest.proto
" - Outputs="google\protobuf\map_lite_unittest.pb.h;google\protobuf\map_lite_unittest.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_lite.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_lite.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite.proto
" - Outputs="google\protobuf\unittest_lite.pb.h;google\protobuf\unittest_lite.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_lite.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite.proto
" - Outputs="google\protobuf\unittest_lite.pb.h;google\protobuf\unittest_lite.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_import_lite.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_import_lite.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_lite.proto
" - Outputs="google\protobuf\unittest_import_lite.pb.h;google\protobuf\unittest_import_lite.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_import_lite.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_lite.proto
" - Outputs="google\protobuf\unittest_import_lite.pb.h;google\protobuf\unittest_import_lite.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_import_public_lite.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_import_public_lite.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_public_lite.proto
" - Outputs="google\protobuf\unittest_import_public_lite.pb.h;google\protobuf\unittest_import_public_lite.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_import_public_lite.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_public_lite.proto
" - Outputs="google\protobuf\unittest_import_public_lite.pb.h;google\protobuf\unittest_import_public_lite.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\map_lite_unittest.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating map_lite_unittest.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/map_lite_unittest.proto
" - Outputs="google\protobuf\map_lite_unittest.pb.h;google\protobuf\map_lite_unittest.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating map_lite_unittest.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/map_lite_unittest.proto
" - Outputs="google\protobuf\map_lite_unittest.pb.h;google\protobuf\map_lite_unittest.pb.cc" - /> - </FileConfiguration> - </File> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/vsprojects/protobuf.sln b/vsprojects/protobuf.sln deleted file mode 100644 index 567dee62..00000000 --- a/vsprojects/protobuf.sln +++ /dev/null @@ -1,92 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libprotobuf", "libprotobuf.vcproj", "{3E283F37-A4ED-41B7-A3E6-A2D89D131A30}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libprotoc", "libprotoc.vcproj", "{B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}" - ProjectSection(ProjectDependencies) = postProject - {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} = {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "protoc", "protoc.vcproj", "{1738D5F6-ED1E-47E0-B2F0-456864B93C1E}" - ProjectSection(ProjectDependencies) = postProject - {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} = {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} - {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} = {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tests", "tests.vcproj", "{4DF72760-C055-40A5-A77E-30A17E2AC2DB}" - ProjectSection(ProjectDependencies) = postProject - {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} = {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} - {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} = {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} - {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7} = {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7} - {3AF54C8A-10BF-4332-9147-F68ED9862032} = {3AF54C8A-10BF-4332-9147-F68ED9862032} - {CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32} = {CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32} - {1738D5F6-ED1E-47E0-B2F0-456864B93C1E} = {1738D5F6-ED1E-47E0-B2F0-456864B93C1E} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest", "..\gtest\msvc\gtest.vcproj", "{C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest_main", "..\gtest\msvc\gtest_main.vcproj", "{3AF54C8A-10BF-4332-9147-F68ED9862032}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libprotobuf-lite", "libprotobuf-lite.vcproj", "{49EA010D-706F-4BE2-A397-77854B72A040}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lite-test", "lite-test.vcproj", "{12015ACE-42BE-4952-A5A0-44A9A46908E2}" - ProjectSection(ProjectDependencies) = postProject - {49EA010D-706F-4BE2-A397-77854B72A040} = {49EA010D-706F-4BE2-A397-77854B72A040} - {1738D5F6-ED1E-47E0-B2F0-456864B93C1E} = {1738D5F6-ED1E-47E0-B2F0-456864B93C1E} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_plugin", "test_plugin.vcproj", "{CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32}" - ProjectSection(ProjectDependencies) = postProject - {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} = {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} - {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} = {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} - {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7} = {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Debug|Win32.ActiveCfg = Debug|Win32 - {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Debug|Win32.Build.0 = Debug|Win32 - {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Release|Win32.ActiveCfg = Release|Win32 - {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Release|Win32.Build.0 = Release|Win32 - {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Debug|Win32.ActiveCfg = Debug|Win32 - {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Debug|Win32.Build.0 = Debug|Win32 - {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Release|Win32.ActiveCfg = Release|Win32 - {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Release|Win32.Build.0 = Release|Win32 - {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Debug|Win32.ActiveCfg = Debug|Win32 - {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Debug|Win32.Build.0 = Debug|Win32 - {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Release|Win32.ActiveCfg = Release|Win32 - {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Release|Win32.Build.0 = Release|Win32 - {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Debug|Win32.ActiveCfg = Debug|Win32 - {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Debug|Win32.Build.0 = Debug|Win32 - {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Release|Win32.ActiveCfg = Release|Win32 - {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Release|Win32.Build.0 = Release|Win32 - {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Debug|Win32.ActiveCfg = Debug|Win32 - {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Debug|Win32.Build.0 = Debug|Win32 - {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Release|Win32.ActiveCfg = Release|Win32 - {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Release|Win32.Build.0 = Release|Win32 - {3AF54C8A-10BF-4332-9147-F68ED9862032}.Debug|Win32.ActiveCfg = Debug|Win32 - {3AF54C8A-10BF-4332-9147-F68ED9862032}.Debug|Win32.Build.0 = Debug|Win32 - {3AF54C8A-10BF-4332-9147-F68ED9862032}.Release|Win32.ActiveCfg = Release|Win32 - {3AF54C8A-10BF-4332-9147-F68ED9862032}.Release|Win32.Build.0 = Release|Win32 - {49EA010D-706F-4BE2-A397-77854B72A040}.Debug|Win32.ActiveCfg = Debug|Win32 - {49EA010D-706F-4BE2-A397-77854B72A040}.Debug|Win32.Build.0 = Debug|Win32 - {49EA010D-706F-4BE2-A397-77854B72A040}.Release|Win32.ActiveCfg = Release|Win32 - {49EA010D-706F-4BE2-A397-77854B72A040}.Release|Win32.Build.0 = Release|Win32 - {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Debug|Win32.ActiveCfg = Debug|Win32 - {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Debug|Win32.Build.0 = Debug|Win32 - {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Release|Win32.ActiveCfg = Release|Win32 - {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Release|Win32.Build.0 = Release|Win32 - {CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32}.Debug|Win32.ActiveCfg = Debug|Win32 - {CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32}.Debug|Win32.Build.0 = Debug|Win32 - {CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32}.Release|Win32.ActiveCfg = Release|Win32 - {CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/vsprojects/protoc.vcproj b/vsprojects/protoc.vcproj deleted file mode 100644 index 4359e238..00000000 --- a/vsprojects/protoc.vcproj +++ /dev/null @@ -1,192 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="protoc" - ProjectGUID="{1738D5F6-ED1E-47E0-B2F0-456864B93C1E}" - Keyword="Win32Proj" - TargetFrameworkVersion="0" - > - <Platforms> - <Platform - Name="Win32" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="$(OutDir)\$(ProjectName)" - ConfigurationType="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305" - Optimization="0" - AdditionalIncludeDirectories="../src;." - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="3" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="4" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - LinkIncremental="2" - GenerateDebugInformation="true" - SubSystem="1" - TargetMachine="1" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCManifestTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCAppVerifierTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="$(OutDir)\$(ProjectName)" - ConfigurationType="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305" - AdditionalIncludeDirectories="../src;." - PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;" - RuntimeLibrary="2" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - LinkIncremental="2" - GenerateDebugInformation="true" - SubSystem="1" - OptimizeReferences="2" - EnableCOMDATFolding="2" - TargetMachine="1" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCManifestTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCAppVerifierTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="Header Files" - Filter="h;hpp;hxx;hm;inl;inc;xsd" - UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" - > - </Filter> - <Filter - Name="Resource Files" - Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" - UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" - > - </Filter> - <Filter - Name="Source Files" - Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" - UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" - > - <File - RelativePath="..\src\google\protobuf\compiler\main.cc" - > - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/vsprojects/readme.txt b/vsprojects/readme.txt deleted file mode 100644 index ad342497..00000000 --- a/vsprojects/readme.txt +++ /dev/null @@ -1,121 +0,0 @@ -This directory contains project files for compiling Protocol Buffers using -MSVC. This is not the recommended way to do Protocol Buffer development -- -we prefer to develop under a Unix-like environment -- but it may be more -accessible to those who primarily work with MSVC. - -Compiling and Installing -======================== - -0) Check whether a gtest directory exists in the upper level directory. If - you checkout the code from github via "git clone", this gtest directory - won't exist and you won't be able to build the tests described below. To - avoid this problem consider downloading one of the release tar balls which - contains gtest already and copying the gest directory from there to your - protobuf directory: - https://github.com/google/protobuf/releases -1) Open protobuf.sln in Microsoft Visual Studio. -2) Choose "Debug" or "Release" configuration as desired.* -3) From the Build menu, choose "Build Solution". Wait for compiling to finish. -4) From a command shell, run tests.exe and lite-test.exe and check that all - tests pass. -5) Run extract_includes.bat to copy all the public headers into a separate - "include" directory (under the top-level package directory). -6) Copy the contents of the include directory to wherever you want to put - headers. -7) Copy protoc.exe wherever you put build tools (probably somewhere in your - PATH). -8) Copy libprotobuf.lib, libprotobuf-lite.lib, and libprotoc.lib wherever you - put libraries. - -* To avoid conflicts between the MSVC debug and release runtime libraries, when - compiling a debug build of your application, you may need to link against a - debug build of libprotobuf.lib. Similarly, release builds should link against - release libs. - -DLLs vs. static linking -======================= - -Static linking is now the default for the Protocol Buffer libraries. Due to -issues with Win32's use of a separate heap for each DLL, as well as binary -compatibility issues between different versions of MSVC's STL library, it is -recommended that you use static linkage only. However, it is possible to -build libprotobuf and libprotoc as DLLs if you really want. To do this, -do the following: - - 1) Open protobuf.sln in MSVC. - 2) For each of the projects libprotobuf, libprotobuf-lite, and libprotoc, do - the following: - 2a) Right-click the project and choose "properties". - 2b) From the side bar, choose "General", under "Configuration Properties". - 2c) Change the "Configuration Type" to "Dynamic Library (.dll)". - 2d) From the side bar, choose "Preprocessor", under "C/C++". - 2e) Add PROTOBUF_USE_DLLS to the list of preprocessor defines. - 3) When compiling your project, make sure to #define PROTOBUF_USE_DLLS. - -When distributing your software to end users, we strongly recommend that you -do NOT install libprotobuf.dll or libprotoc.dll to any shared location. -Instead, keep these libraries next to your binaries, in your application's -own install directory. C++ makes it very difficult to maintain binary -compatibility between releases, so it is likely that future versions of these -libraries will *not* be usable as drop-in replacements. - -If your project is itself a DLL intended for use by third-party software, we -recommend that you do NOT expose protocol buffer objects in your library's -public interface, and that you statically link protocol buffers into your -library. - -ZLib support -============ - -If you want to include GzipInputStream and GzipOutputStream -(google/protobuf/io/gzip_stream.h) in libprotoc, you will need to do a few -additional steps: - -1) Obtain a copy of the zlib library. The pre-compiled DLL at zlib.net works. -2) Make sure zlib's two headers are in your include path and that the .lib file - is in your library path. You could place all three files directly into the - vsproject directory to compile libprotobuf, but they need to be visible to - your own project as well, so you should probably just put them into the - VC shared icnlude and library directories. -3) Right-click on the "tests" project and choose "properties". Navigate the - sidebar to "Configuration Properties" -> "Linker" -> "Input". -4) Under "Additional Dependencies", add the name of the zlib .lib file (e.g. - zdll.lib). Make sure to update both the Debug and Release configurations. -5) If you are compiling libprotobuf and libprotoc as DLLs (see previous - section), repeat steps 2 and 3 for the libprotobuf and libprotoc projects. - If you are compiling them as static libraries, then you will need to link - against the zlib library directly from your own app. -6) Edit config.h (in the vsprojects directory) and un-comment the line that - #defines HAVE_ZLIB. (Or, alternatively, define this macro via the project - settings.) - -Notes on Compiler Warnings -========================== - -The following warnings have been disabled while building the protobuf libraries -and compiler. You may have to disable some of them in your own project as -well, or live with them. - -C4018 - 'expression' : signed/unsigned mismatch -C4146 - unary minus operator applied to unsigned type, result still unsigned -C4244 - Conversion from 'type1' to 'type2', possible loss of data. -C4251 - 'identifier' : class 'type' needs to have dll-interface to be used by - clients of class 'type2' -C4267 - Conversion from 'size_t' to 'type', possible loss of data. -C4305 - 'identifier' : truncation from 'type1' to 'type2' -C4355 - 'this' : used in base member initializer list -C4800 - 'type' : forcing value to bool 'true' or 'false' (performance warning) -C4996 - 'function': was declared deprecated - -C4251 is of particular note, if you are compiling the Protocol Buffer library -as a DLL (see previous section). The protocol buffer library uses templates in -its public interfaces. MSVC does not provide any reasonable way to export -template classes from a DLL. However, in practice, it appears that exporting -templates is not necessary anyway. Since the complete definition of any -template is available in the header files, anyone importing the DLL will just -end up compiling instances of the templates into their own binary. The -Protocol Buffer implementation does not rely on static template members being -unique, so there should be no problem with this, but MSVC prints warning -nevertheless. So, we disable it. Unfortunately, this warning will also be -produced when compiling code which merely uses protocol buffers, meaning you -may have to disable it in your code too. diff --git a/vsprojects/test_plugin.vcproj b/vsprojects/test_plugin.vcproj deleted file mode 100755 index 549f9503..00000000 --- a/vsprojects/test_plugin.vcproj +++ /dev/null @@ -1,209 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="test_plugin" - ProjectGUID="{CBBD34E5-02B0-40D5-B6D8-BFEA83E18B32}" - RootNamespace="test_plugin" - Keyword="Win32Proj" - TargetFrameworkVersion="196613" - > - <Platforms> - <Platform - Name="Win32" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="$(OutDir)\$(ProjectName)" - ConfigurationType="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - Description="" - CommandLine="" - AdditionalDependencies="" - Outputs="" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305" - Optimization="0" - AdditionalIncludeDirectories="../src;.;../gtest/include" - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_VARIADIC_MAX=10;" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="3" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="4" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - LinkIncremental="2" - GenerateDebugInformation="true" - SubSystem="1" - TargetMachine="1" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCManifestTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCAppVerifierTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="$(OutDir)\$(ProjectName)" - ConfigurationType="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - Description="" - CommandLine="" - AdditionalDependencies="" - Outputs="" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305" - AdditionalIncludeDirectories="../src;.;../gtest/include" - PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_VARIADIC_MAX=10;" - RuntimeLibrary="2" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - LinkIncremental="2" - GenerateDebugInformation="true" - SubSystem="1" - OptimizeReferences="2" - EnableCOMDATFolding="2" - TargetMachine="1" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCManifestTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCAppVerifierTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="Header Files" - Filter="h;hpp;hxx;hm;inl;inc;xsd" - > - <File - RelativePath="..\src\google\protobuf\compiler\mock_code_generator.h" - > - </File> - <File - RelativePath="..\src\google\protobuf\testing\file.h" - > - </File> - </Filter> - <Filter - Name="Source Files" - Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" - > - <File - RelativePath="..\src\google\protobuf\compiler\test_plugin.cc" - > - </File> - <File - RelativePath="..\src\google\protobuf\compiler\mock_code_generator.cc" - > - </File> - <File - RelativePath="..\src\google\protobuf\testing\file.cc" - > - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/vsprojects/tests.vcproj b/vsprojects/tests.vcproj deleted file mode 100644 index 792a3fd8..00000000 --- a/vsprojects/tests.vcproj +++ /dev/null @@ -1,964 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="tests" - ProjectGUID="{4DF72760-C055-40A5-A77E-30A17E2AC2DB}" - RootNamespace="tests" - Keyword="Win32Proj" - TargetFrameworkVersion="0" - > - <Platforms> - <Platform - Name="Win32" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="Debug" - IntermediateDirectory="$(OutDir)\$(ProjectName)" - ConfigurationType="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - Description="" - CommandLine="" - AdditionalDependencies="" - Outputs="" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305" - Optimization="0" - AdditionalIncludeDirectories="../src;.;../gtest/include" - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_VARIADIC_MAX=10;" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="3" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="4" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - LinkIncremental="2" - GenerateDebugInformation="true" - SubSystem="1" - TargetMachine="1" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCManifestTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCAppVerifierTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="Release" - IntermediateDirectory="$(OutDir)\$(ProjectName)" - ConfigurationType="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - Description="" - CommandLine="" - AdditionalDependencies="" - Outputs="" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305" - AdditionalIncludeDirectories="../src;.;../gtest/include" - PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_VARIADIC_MAX=10;" - RuntimeLibrary="2" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - LinkIncremental="2" - GenerateDebugInformation="true" - SubSystem="1" - OptimizeReferences="2" - EnableCOMDATFolding="2" - TargetMachine="1" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCManifestTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCAppVerifierTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="Header Files" - Filter="h;hpp;hxx;hm;inl;inc;xsd" - UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" - > - <File RelativePath=".\google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.h"></File> - <File RelativePath=".\google\protobuf\unittest.pb.h"></File> - <File RelativePath=".\google\protobuf\unittest_custom_options.pb.h"></File> - <File RelativePath=".\google\protobuf\unittest_embed_optimize_for.pb.h"></File> - <File RelativePath=".\google\protobuf\unittest_import.pb.h"></File> - <File RelativePath=".\google\protobuf\unittest_import_public.pb.h"></File> - <File RelativePath=".\google\protobuf\unittest_lite_imports_nonline.pb.h"></File> - <File RelativePath=".\google\protobuf\unittest_mset.pb.h"></File> - <File RelativePath=".\google\protobuf\unittest_no_generic_services.pb.h"></File> - <File RelativePath=".\google\protobuf\unittest_optimize_for.pb.h"></File> - <File RelativePath="..\src\google\protobuf\testing\file.h"></File> - <File RelativePath="..\src\google\protobuf\testing\googletest.h"></File> - <File RelativePath="..\src\google\protobuf\test_util.h"></File> - <File RelativePath="..\src\google\protobuf\map_test_util_impl.h"></File> - <File RelativePath="..\src\google\protobuf\map_test_util.h"></File> - <File RelativePath="..\src\google\protobuf\arena_test_util.h"></File> - <File RelativePath="..\src\google\protobuf\compiler\mock_code_generator.h"></File> - </Filter> - <Filter - Name="Resource Files" - Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" - UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" - > - </Filter> - <Filter - Name="Source Files" - Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" - UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" - > - <File RelativePath=".\google\protobuf\map_lite_unittest.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_import_lite.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_lite.pb.cc"></File> - <File RelativePath=".\google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.cc"></File> - <File RelativePath=".\google\protobuf\compiler\cpp\cpp_test_large_enum_value.pb.cc"></File> - <File RelativePath=".\google\protobuf\any_test.pb.cc"></File> - <File RelativePath=".\google\protobuf\map_proto2_unittest.pb.cc"></File> - <File RelativePath=".\google\protobuf\map_unittest.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_arena.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_custom_options.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_drop_unknown_fields.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_embed_optimize_for.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_empty.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_import.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_import_public_lite.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_import_public.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_lite_imports_nonlite.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_mset.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_no_arena_import.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_no_arena.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_no_field_presence.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_no_generic_services.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_optimize_for.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_preserve_unknown_enum2.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_preserve_unknown_enum.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_proto3_arena.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest_well_known_types.pb.cc"></File> - <File RelativePath=".\google\protobuf\unittest.pb.cc"></File> - <File RelativePath="..\src\google\protobuf\any_test.cc"></File> - <File RelativePath="..\src\google\protobuf\arenastring_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\arena_test_util.cc"></File> - <File RelativePath="..\src\google\protobuf\arena_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\command_line_interface_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_bootstrap_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_plugin_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_generator_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\importer_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\java\java_plugin_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\mock_code_generator.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\objectivec\objectivec_helpers_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\parser_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\compiler\python\python_plugin_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\descriptor_database_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\descriptor_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\drop_unknown_fields_test.cc"></File> - <File RelativePath="..\src\google\protobuf\dynamic_message_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\extension_set_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\generated_message_reflection_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\io\coded_stream_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\io\printer_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\io\tokenizer_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\io\zero_copy_stream_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\map_field_test.cc"></File> - <File RelativePath="..\src\google\protobuf\map_test.cc"></File> - <File RelativePath="..\src\google\protobuf\map_test_util.cc"></File> - <File RelativePath="..\src\google\protobuf\message_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\no_field_presence_test.cc"></File> - <File RelativePath="..\src\google\protobuf\preserve_unknown_enum_test.cc"></File> - <File RelativePath="..\src\google\protobuf\proto3_arena_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\reflection_ops_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\repeated_field_reflection_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\repeated_field_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\common_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\once_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\stringprintf_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\structurally_valid_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\strutil_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\template_util_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\stubs\type_traits_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\testing\file.cc"></File> - <File RelativePath="..\src\google\protobuf\testing\googletest.cc"></File> - <File RelativePath="..\src\google\protobuf\test_util.cc"></File> - <File RelativePath="..\src\google\protobuf\text_format_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\unknown_field_set_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\well_known_types_unittest.cc"></File> - <File RelativePath="..\src\google\protobuf\wire_format_unittest.cc"></File> - </Filter> - <File - RelativePath="..\src\google\protobuf\any_test.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating any_test.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/any_test.proto" - Outputs="google\protobuf\any_test.pb.h;google\protobuf\any_test.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating any_test.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/any_test.proto" - Outputs="google\protobuf\any_test.pb.h;google\protobuf\any_test.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_preserve_unknown_enum2.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_preserve_unknown_enum2.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_preserve_unknown_enum2.proto" - Outputs="google\protobuf\unittest_preserve_unknown_enum2.pb.h;google\protobuf\unittest_preserve_unknown_enum2.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_preserve_unknown_enum2.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_preserve_unknown_enum2.proto" - Outputs="google\protobuf\unittest_preserve_unknown_enum2.pb.h;google\protobuf\unittest_preserve_unknown_enum2.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_well_known_types.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_well_known_types.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_well_known_types.proto" - Outputs="google\protobuf\unittest_well_known_types.pb.h;google\protobuf\unittest_well_known_types.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_well_known_types.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_well_known_types.proto" - Outputs="google\protobuf\unittest_well_known_types.pb.h;google\protobuf\unittest_well_known_types.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\map_lite_unittest.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating map_lite_unittest.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/map_lite_unittest.proto" - Outputs="google\protobuf\map_lite_unittest.pb.h;google\protobuf\map_lite_unittest.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating map_lite_unittest.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/map_lite_unittest.proto" - Outputs="google\protobuf\map_lite_unittest.pb.h;google\protobuf\map_lite_unittest.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\map_proto2_unittest.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating map_proto2_unittest.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/map_proto2_unittest.proto" - Outputs="google\protobuf\map_proto2_unittest.pb.h;google\protobuf\map_proto2_unittest.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating map_proto2_unittest.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/map_proto2_unittest.proto" - Outputs="google\protobuf\map_proto2_unittest.pb.h;google\protobuf\map_proto2_unittest.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\map_unittest.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating map_unittest.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/map_unittest.proto" - Outputs="google\protobuf\map_unittest.pb.h;google\protobuf\map_unittest.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating map_unittest.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/map_unittest.proto" - Outputs="google\protobuf\map_unittest.pb.h;google\protobuf\map_unittest.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest.proto" - Outputs="google\protobuf\unittest.pb.h;google\protobuf\unittest.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest.proto" - Outputs="google\protobuf\unittest.pb.h;google\protobuf\unittest.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_arena.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_arena.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_arena.proto" - Outputs="google\protobuf\unittest_arena.pb.h;google\protobuf\unittest_arena.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_arena.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_arena.proto" - Outputs="google\protobuf\unittest_arena.pb.h;google\protobuf\unittest_arena.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_custom_options.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_custom_options.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_custom_options.proto" - Outputs="google\protobuf\unittest_custom_options.pb.h;google\protobuf\unittest_custom_options.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_custom_options.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_custom_options.proto" - Outputs="google\protobuf\unittest_custom_options.pb.h;google\protobuf\unittest_custom_options.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_drop_unknown_fields.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_drop_unknown_fields.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_drop_unknown_fields.proto" - Outputs="google\protobuf\unittest_drop_unknown_fields.pb.h;google\protobuf\unittest_drop_unknown_fields.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_drop_unknown_fields.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_drop_unknown_fields.proto" - Outputs="google\protobuf\unittest_drop_unknown_fields.pb.h;google\protobuf\unittest_drop_unknown_fields.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_embed_optimize_for.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_embed_optimize_for.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_embed_optimize_for.proto" - Outputs="google\protobuf\unittest_embed_optimize_for.pb.h;google\protobuf\unittest_embed_optimize_for.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_embed_optimize_for.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_embed_optimize_for.proto" - Outputs="google\protobuf\unittest_embed_optimize_for.pb.h;google\protobuf\unittest_embed_optimize_for.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_empty.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_empty.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_empty.proto" - Outputs="google\protobuf\unittest_empty.pb.h;google\protobuf\unittest_empty.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_empty.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_empty.proto" - Outputs="google\protobuf\unittest_empty.pb.h;google\protobuf\unittest_empty.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_import_lite.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_import_lite.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_lite.proto" - Outputs="google\protobuf\unittest_import_lite.pb.h;google\protobuf\unittest_import_lite.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_import_lite.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_lite.proto" - Outputs="google\protobuf\unittest_import_lite.pb.h;google\protobuf\unittest_import_lite.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_import.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_import.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import.proto" - Outputs="google\protobuf\unittest_import.pb.h;google\protobuf\unittest_import.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_import.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import.proto" - Outputs="google\protobuf\unittest_import.pb.h;google\protobuf\unittest_import.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_import_public_lite.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_import_public_lite.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_public_lite.proto" - Outputs="google\protobuf\unittest_import_public_lite.pb.h;google\protobuf\unittest_import_public_lite.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_import_public_lite.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_public_lite.proto" - Outputs="google\protobuf\unittest_import_public_lite.pb.h;google\protobuf\unittest_import_public_lite.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_import_public.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_import_public.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_public.proto" - Outputs="google\protobuf\unittest_import_public.pb.h;google\protobuf\unittest_import_public.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_import_public.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_public.proto" - Outputs="google\protobuf\unittest_import_public.pb.h;google\protobuf\unittest_import_public.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_lite_imports_nonlite.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_lite_imports_nonlite.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite_imports_nonlite.proto" - Outputs="google\protobuf\unittest_lite_imports_nonlite.pb.h;google\protobuf\unittest_lite_imports_nonlite.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_lite_imports_nonlite.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite_imports_nonlite.proto" - Outputs="google\protobuf\unittest_lite_imports_nonlite.pb.h;google\protobuf\unittest_lite_imports_nonlite.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_lite.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_lite.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite.proto" - Outputs="google\protobuf\unittest_lite.pb.h;google\protobuf\unittest_lite.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_lite.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite.proto" - Outputs="google\protobuf\unittest_lite.pb.h;google\protobuf\unittest_lite.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_mset.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_mset.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_mset.proto" - Outputs="google\protobuf\unittest_mset.pb.h;google\protobuf\unittest_mset.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_mset.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_mset.proto" - Outputs="google\protobuf\unittest_mset.pb.h;google\protobuf\unittest_mset.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_no_arena_import.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_no_arena_import.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_no_arena_import.proto" - Outputs="google\protobuf\unittest_no_arena_import.pb.h;google\protobuf\unittest_no_arena_import.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_no_arena_import.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_no_arena_import.proto" - Outputs="google\protobuf\unittest_no_arena_import.pb.h;google\protobuf\unittest_no_arena_import.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_no_arena.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_no_arena.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_no_arena.proto" - Outputs="google\protobuf\unittest_no_arena.pb.h;google\protobuf\unittest_no_arena.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_no_arena.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_no_arena.proto" - Outputs="google\protobuf\unittest_no_arena.pb.h;google\protobuf\unittest_no_arena.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_no_field_presence.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_no_field_presence.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_no_field_presence.proto" - Outputs="google\protobuf\unittest_no_field_presence.pb.h;google\protobuf\unittest_no_field_presence.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_no_field_presence.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_no_field_presence.proto" - Outputs="google\protobuf\unittest_no_field_presence.pb.h;google\protobuf\unittest_no_field_presence.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_no_generic_services.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_no_generic_services.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_no_generic_services.proto" - Outputs="google\protobuf\unittest_no_generic_services.pb.h;google\protobuf\unittest_no_generic_services.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_no_generic_services.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_no_generic_services.proto" - Outputs="google\protobuf\unittest_no_generic_services.pb.h;google\protobuf\unittest_no_generic_services.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_optimize_for.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_optimize_for.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_optimize_for.proto" - Outputs="google\protobuf\unittest_optimize_for.pb.h;google\protobuf\unittest_optimize_for.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_optimize_for.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_optimize_for.proto" - Outputs="google\protobuf\unittest_optimize_for.pb.h;google\protobuf\unittest_optimize_for.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_preserve_unknown_enum.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_preserve_unknown_enum.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_preserve_unknown_enum.proto" - Outputs="google\protobuf\unittest_preserve_unknown_enum.pb.h;google\protobuf\unittest_preserve_unknown_enum.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_preserve_unknown_enum.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_preserve_unknown_enum.proto" - Outputs="google\protobuf\unittest_preserve_unknown_enum.pb.h;google\protobuf\unittest_preserve_unknown_enum.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\unittest_proto3_arena.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_proto3_arena.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_proto3_arena.proto" - Outputs="google\protobuf\unittest_proto3_arena.pb.h;google\protobuf\unittest_proto3_arena.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating unittest_proto3_arena.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_proto3_arena.proto" - Outputs="google\protobuf\unittest_proto3_arena.pb.h;google\protobuf\unittest_proto3_arena.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\compiler\cpp\cpp_test_bad_identifiers.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating cpp_test_bad_identifiers.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto" - Outputs="google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.h;google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating cpp_test_bad_identifiers.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto" - Outputs="google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.h;google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.cc" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\src\google\protobuf\compiler\cpp\cpp_test_large_enum_value.proto" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating cpp_test_large_enum_value.pb.{h,cc}..." - CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto" - Outputs="google\protobuf\compiler\cpp\cpp_test_large_enum_value.pb.h;google\protobuf\compiler\cpp\cpp_test_large_enum_value.pb.cc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCustomBuildTool" - Description="Generating cpp_test_large_enum_value.pb.{h,cc}..." - CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto" - Outputs="google\protobuf\compiler\cpp\cpp_test_large_enum_value.pb.h;google\protobuf\compiler\cpp\cpp_test_large_enum_value.pb.cc" - /> - </FileConfiguration> - </File> - </Files> - <Globals> - </Globals> -</VisualStudioProject> |