diff options
Diffstat (limited to 'src')
195 files changed, 18829 insertions, 3562 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 815c9ae9..02b8cd72 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,19 +24,41 @@ AM_LDFLAGS = $(PTHREAD_CFLAGS) # If I say "dist_include_DATA", automake complains that $(includedir) is not # a "legitimate" directory for DATA. Screw you, automake. protodir = $(includedir) -nobase_dist_proto_DATA = google/protobuf/descriptor.proto \ +nobase_dist_proto_DATA = google/protobuf/descriptor.proto \ + google/protobuf/any.proto \ + google/protobuf/api.proto \ + google/protobuf/duration.proto \ + google/protobuf/empty.proto \ + google/protobuf/field_mask.proto \ + google/protobuf/source_context.proto \ + google/protobuf/struct.proto \ + google/protobuf/timestamp.proto \ + google/protobuf/type.proto \ + google/protobuf/wrappers.proto \ google/protobuf/compiler/plugin.proto # Not sure why these don't get cleaned automatically. clean-local: rm -f *.loT -CLEANFILES = $(protoc_outputs) unittest_proto_middleman \ +public_config = google/protobuf/stubs/pbconfig.h + +CLEANFILES = $(protoc_outputs) $(public_config) 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 \ @@ -54,11 +76,13 @@ nobase_include_HEADERS = \ google/protobuf/stubs/atomicops_internals_x86_gcc.h \ google/protobuf/stubs/atomicops_internals_x86_msvc.h \ google/protobuf/stubs/casts.h \ - google/protobuf/stubs/singleton.h \ google/protobuf/stubs/common.h \ google/protobuf/stubs/fastmem.h \ + google/protobuf/stubs/hash.h \ google/protobuf/stubs/once.h \ google/protobuf/stubs/platform_macros.h \ + google/protobuf/stubs/shared_ptr.h \ + google/protobuf/stubs/singleton.h \ google/protobuf/stubs/stl_util.h \ google/protobuf/stubs/template_util.h \ google/protobuf/stubs/type_traits.h \ @@ -70,10 +94,13 @@ nobase_include_HEADERS = \ google/protobuf/dynamic_message.h \ google/protobuf/extension_set.h \ google/protobuf/generated_enum_reflection.h \ + google/protobuf/generated_enum_util.h \ google/protobuf/generated_message_reflection.h \ google/protobuf/generated_message_util.h \ google/protobuf/map_entry.h \ + google/protobuf/map_entry_lite.h \ google/protobuf/map_field.h \ + google/protobuf/map_field_lite.h \ google/protobuf/map_field_inl.h \ google/protobuf/map.h \ google/protobuf/map_type_handler.h \ @@ -106,12 +133,19 @@ nobase_include_HEADERS = \ google/protobuf/compiler/plugin.pb.h \ google/protobuf/compiler/cpp/cpp_generator.h \ google/protobuf/compiler/java/java_generator.h \ - google/protobuf/compiler/python/python_generator.h + google/protobuf/compiler/java/java_names.h \ + google/protobuf/compiler/javanano/javanano_generator.h \ + google/protobuf/compiler/objectivec/objectivec_generator.h \ + google/protobuf/compiler/python/python_generator.h \ + google/protobuf/compiler/ruby/ruby_generator.h + +nobase_nodist_include_HEADERS = \ + $(public_config) lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la libprotobuf_lite_la_LIBADD = $(PTHREAD_LIBS) -libprotobuf_lite_la_LDFLAGS = -version-info 9:2:0 -export-dynamic -no-undefined +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 \ @@ -126,7 +160,6 @@ libprotobuf_lite_la_SOURCES = \ google/protobuf/arenastring.cc \ google/protobuf/extension_set.cc \ google/protobuf/generated_message_util.cc \ - google/protobuf/map_field.cc \ google/protobuf/message_lite.cc \ google/protobuf/repeated_field.cc \ google/protobuf/wire_format_lite.cc \ @@ -134,9 +167,10 @@ 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 9:2:0 -export-dynamic -no-undefined +libprotobuf_la_LDFLAGS = -version-info 10:0:0 -export-dynamic -no-undefined libprotobuf_la_SOURCES = \ $(libprotobuf_lite_la_SOURCES) \ google/protobuf/stubs/strutil.cc \ @@ -150,6 +184,7 @@ libprotobuf_la_SOURCES = \ google/protobuf/dynamic_message.cc \ google/protobuf/extension_set_heavy.cc \ google/protobuf/generated_message_reflection.cc \ + google/protobuf/map_field.cc \ google/protobuf/message.cc \ google/protobuf/reflection_internal.h \ google/protobuf/reflection_ops.cc \ @@ -164,9 +199,10 @@ libprotobuf_la_SOURCES = \ google/protobuf/io/zero_copy_stream_impl.cc \ google/protobuf/compiler/importer.cc \ google/protobuf/compiler/parser.cc +nodist_libprotobuf_la_SOURCES = $(nodist_libprotobuf_lite_la_SOURCES) libprotoc_la_LIBADD = $(PTHREAD_LIBS) libprotobuf.la -libprotoc_la_LDFLAGS = -version-info 9:2:0 -export-dynamic -no-undefined +libprotoc_la_LDFLAGS = -version-info 10:0:0 -export-dynamic -no-undefined libprotoc_la_SOURCES = \ google/protobuf/compiler/code_generator.cc \ google/protobuf/compiler/command_line_interface.cc \ @@ -239,7 +275,54 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/java/java_string_field.h \ google/protobuf/compiler/java/java_doc_comment.cc \ google/protobuf/compiler/java/java_doc_comment.h \ - google/protobuf/compiler/python/python_generator.cc + google/protobuf/compiler/javanano/javanano_enum.cc \ + google/protobuf/compiler/javanano/javanano_enum.h \ + google/protobuf/compiler/javanano/javanano_enum_field.cc \ + google/protobuf/compiler/javanano/javanano_enum_field.h \ + google/protobuf/compiler/javanano/javanano_extension.cc \ + google/protobuf/compiler/javanano/javanano_extension.h \ + google/protobuf/compiler/javanano/javanano_field.cc \ + google/protobuf/compiler/javanano/javanano_field.h \ + google/protobuf/compiler/javanano/javanano_file.cc \ + google/protobuf/compiler/javanano/javanano_file.h \ + google/protobuf/compiler/javanano/javanano_generator.cc \ + google/protobuf/compiler/javanano/javanano_generator.h \ + google/protobuf/compiler/javanano/javanano_helpers.cc \ + google/protobuf/compiler/javanano/javanano_helpers.h \ + google/protobuf/compiler/javanano/javanano_map_field.cc \ + google/protobuf/compiler/javanano/javanano_map_field.h \ + google/protobuf/compiler/javanano/javanano_message.cc \ + google/protobuf/compiler/javanano/javanano_message.h \ + google/protobuf/compiler/javanano/javanano_message_field.cc \ + google/protobuf/compiler/javanano/javanano_message_field.h \ + google/protobuf/compiler/javanano/javanano_params.h \ + google/protobuf/compiler/javanano/javanano_primitive_field.cc \ + google/protobuf/compiler/javanano/javanano_primitive_field.h \ + google/protobuf/compiler/objectivec/objectivec_enum.cc \ + google/protobuf/compiler/objectivec/objectivec_enum.h \ + google/protobuf/compiler/objectivec/objectivec_enum_field.cc \ + google/protobuf/compiler/objectivec/objectivec_enum_field.h \ + google/protobuf/compiler/objectivec/objectivec_extension.cc \ + google/protobuf/compiler/objectivec/objectivec_extension.h \ + google/protobuf/compiler/objectivec/objectivec_field.cc \ + google/protobuf/compiler/objectivec/objectivec_field.h \ + google/protobuf/compiler/objectivec/objectivec_file.cc \ + google/protobuf/compiler/objectivec/objectivec_file.h \ + google/protobuf/compiler/objectivec/objectivec_generator.cc \ + google/protobuf/compiler/objectivec/objectivec_helpers.cc \ + google/protobuf/compiler/objectivec/objectivec_helpers.h \ + google/protobuf/compiler/objectivec/objectivec_map_field.cc \ + google/protobuf/compiler/objectivec/objectivec_map_field.h \ + google/protobuf/compiler/objectivec/objectivec_message.cc \ + google/protobuf/compiler/objectivec/objectivec_message.h \ + google/protobuf/compiler/objectivec/objectivec_message_field.cc \ + google/protobuf/compiler/objectivec/objectivec_message_field.h \ + google/protobuf/compiler/objectivec/objectivec_oneof.cc \ + google/protobuf/compiler/objectivec/objectivec_oneof.h \ + google/protobuf/compiler/objectivec/objectivec_primitive_field.cc \ + google/protobuf/compiler/objectivec/objectivec_primitive_field.h \ + google/protobuf/compiler/python/python_generator.cc \ + google/protobuf/compiler/ruby/ruby_generator.cc bin_PROGRAMS = protoc protoc_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la @@ -270,8 +353,10 @@ protoc_inputs = \ 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/compiler/cpp/cpp_test_bad_identifiers.proto + google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto \ + google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto EXTRA_DIST = \ $(protoc_inputs) \ @@ -280,6 +365,7 @@ EXTRA_DIST = \ google/protobuf/io/gzip_stream_unittest.sh \ google/protobuf/testdata/golden_message \ google/protobuf/testdata/golden_message_oneof_implemented \ + google/protobuf/testdata/golden_message_proto3 \ google/protobuf/testdata/golden_packed_fields_message \ google/protobuf/testdata/bad_utf8_string \ google/protobuf/testdata/text_format_unittest_data.txt \ @@ -295,6 +381,8 @@ EXTRA_DIST = \ google/protobuf/unittest_enormous_descriptor.proto protoc_lite_outputs = \ + google/protobuf/map_lite_unittest.pb.cc \ + google/protobuf/map_lite_unittest.pb.h \ google/protobuf/unittest_lite.pb.cc \ google/protobuf/unittest_lite.pb.h \ google/protobuf/unittest_import_lite.pb.cc \ @@ -304,8 +392,6 @@ protoc_lite_outputs = \ protoc_outputs = \ $(protoc_lite_outputs) \ - google/protobuf/map_lite_unittest.pb.cc \ - google/protobuf/map_lite_unittest.pb.h \ google/protobuf/map_proto2_unittest.pb.cc \ google/protobuf/map_proto2_unittest.pb.h \ google/protobuf/map_unittest.pb.cc \ @@ -342,12 +428,16 @@ protoc_outputs = \ 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/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 = $(protoc_outputs) +BUILT_SOURCES = $(public_config) $(protoc_outputs) if USE_EXTERNAL_PROTOC @@ -369,8 +459,11 @@ endif $(protoc_outputs): unittest_proto_middleman COMMON_TEST_SOURCES = \ + google/protobuf/arena_test_util.cc \ + google/protobuf/arena_test_util.h \ google/protobuf/map_test_util.cc \ google/protobuf/map_test_util.h \ + google/protobuf/map_test_util_impl.h \ google/protobuf/test_util.cc \ google/protobuf/test_util.h \ google/protobuf/testing/googletest.cc \ @@ -432,7 +525,9 @@ protobuf_test_SOURCES = \ google/protobuf/compiler/cpp/cpp_plugin_unittest.cc \ google/protobuf/compiler/java/java_plugin_unittest.cc \ google/protobuf/compiler/java/java_doc_comment_unittest.cc \ + google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc \ google/protobuf/compiler/python/python_plugin_unittest.cc \ + google/protobuf/compiler/ruby/ruby_generator_unittest.cc \ $(COMMON_TEST_SOURCES) nodist_protobuf_test_SOURCES = $(protoc_outputs) @@ -455,8 +550,12 @@ protobuf_lite_test_LDADD = $(PTHREAD_LIBS) libprotobuf-lite.la protobuf_lite_test_CXXFLAGS = $(NO_OPT_CXXFLAGS) protobuf_lite_test_SOURCES = \ google/protobuf/lite_unittest.cc \ + google/protobuf/map_lite_test_util.cc \ + google/protobuf/map_lite_test_util.h \ google/protobuf/test_util_lite.cc \ google/protobuf/test_util_lite.h + # TODO(teboring) add the file back and make the test build. + # google/protobuf/map_lite_test.cc nodist_protobuf_lite_test_SOURCES = $(protoc_lite_outputs) # Test plugin binary. diff --git a/src/google/protobuf/SEBS b/src/google/protobuf/SEBS deleted file mode 100644 index ba33c732..00000000 --- a/src/google/protobuf/SEBS +++ /dev/null @@ -1,240 +0,0 @@ -# **EXPERIMENTAL** -# -# See http://sebs.googlecode.com -# -# This is an experimental build definition file using the SEBS build system. -# I (Kenton Varda, maintainer of Protocol Buffers) happen to be the author of -# SEBS, though SEBS is not a Google project. I'm sticking this file in -# protobuf's SVN because that's the easiest place for me to put it, and it -# shouldn't harm anyone. This file is not included in the distribution. -# -# Currently, to use this file, you must generate config.h and put it at the -# top level of the source tree. - -_cpp = sebs.import_("//sebs/cpp.sebs") - -# ==================================================================== -# Public targets - -protobuf_lite = _cpp.Library( - name = "protobuf-lite", - srcs = [ "stubs/common.cc", - "stubs/once.cc", - "stubs/hash.cc", - "stubs/hash.h", - "stubs/map-util.h", - "stubs/stl_util-inl.h", - "extension_set.cc", - "generated_message_util.cc", - "message_lite.cc", - "repeated_field.cc", - "wire_format_lite.cc", - "io/coded_stream.cc", - "io/zero_copy_stream.cc", - "io/zero_copy_stream_impl_lite.cc" ], - deps = [ _cpp.SystemLibrary(name = "pthread") ]) - -protobuf = _cpp.Library( - name = "protobuf", - srcs = [ "stubs/strutil.cc", - "stubs/strutil.h", - "stubs/substitute.cc", - "stubs/substitute.h", - "stubs/structurally_valid.cc", - "descriptor.cc", - "descriptor.pb.cc", - "descriptor_database.cc", - "dynamic_message.cc", - "extension_set_heavy.cc", - "generated_message_reflection.cc", - "message.cc", - "reflection_ops.cc", - "service.cc", - "text_format.cc", - "unknown_field_set.cc", - "wire_format.cc", - "io/gzip_stream.cc", - "io/printer.cc", - "io/tokenizer.cc", - "io/zero_copy_stream_impl.cc", - "compiler/importer.cc", - "compiler/parser.cc" ], - deps = [ protobuf_lite, - _cpp.SystemLibrary(name = "z") ]) - -libprotoc = _cpp.Library( - name = "protoc", - srcs = [ "compiler/code_generator.cc", - "compiler/command_line_interface.cc", - "compiler/cpp/cpp_enum.cc", - "compiler/cpp/cpp_enum.h", - "compiler/cpp/cpp_enum_field.cc", - "compiler/cpp/cpp_enum_field.h", - "compiler/cpp/cpp_extension.cc", - "compiler/cpp/cpp_extension.h", - "compiler/cpp/cpp_field.cc", - "compiler/cpp/cpp_field.h", - "compiler/cpp/cpp_file.cc", - "compiler/cpp/cpp_file.h", - "compiler/cpp/cpp_generator.cc", - "compiler/cpp/cpp_helpers.cc", - "compiler/cpp/cpp_helpers.h", - "compiler/cpp/cpp_message.cc", - "compiler/cpp/cpp_message.h", - "compiler/cpp/cpp_message_field.cc", - "compiler/cpp/cpp_message_field.h", - "compiler/cpp/cpp_primitive_field.cc", - "compiler/cpp/cpp_primitive_field.h", - "compiler/cpp/cpp_service.cc", - "compiler/cpp/cpp_service.h", - "compiler/cpp/cpp_string_field.cc", - "compiler/cpp/cpp_string_field.h", - "compiler/java/java_enum.cc", - "compiler/java/java_enum.h", - "compiler/java/java_enum_field.cc", - "compiler/java/java_enum_field.h", - "compiler/java/java_extension.cc", - "compiler/java/java_extension.h", - "compiler/java/java_field.cc", - "compiler/java/java_field.h", - "compiler/java/java_file.cc", - "compiler/java/java_file.h", - "compiler/java/java_generator.cc", - "compiler/java/java_helpers.cc", - "compiler/java/java_helpers.h", - "compiler/java/java_message.cc", - "compiler/java/java_message.h", - "compiler/java/java_message_field.cc", - "compiler/java/java_message_field.h", - "compiler/java/java_primitive_field.cc", - "compiler/java/java_primitive_field.h", - "compiler/java/java_service.cc", - "compiler/java/java_service.h", - "compiler/python/python_generator.cc" ], - deps = [ protobuf ]) - -protoc = _cpp.Binary( - name = "protoc", - srcs = [ "compiler/main.cc" ], - deps = [ libprotoc ]) - -# ==================================================================== -# ProtobufLibrary rule class - -class ProtobufLibrary(sebs.Rule): - argument_spec = sebs.ArgumentSpec(srcs = [sebs.Artifact], - deps = ([sebs.Rule], []), - lite = (bool, False)) - - def _expand(self, args): - for dep in args.deps: - if not isinstance(dep, ProtobufLibrary): - raise sebs.DefinitionError( - "Dependency of ProtobufLibrary is not a ProtobufLibrary: %s" % dep) - - protoc.expand_once() - - # We must build protoc for the host configuration to allow cross-compiling. - host_protoc = self.context.configured_artifact(protoc.binary, "host") - - protoc_action = self.context.action(self, "protobuf") - protoc_args = [host_protoc, "-Isrc", "-Itmp", "-Iinclude","--cpp_out=tmp"] - - cpp_srcs = [] - for src in args.srcs: - protoc_args.append(src) - - # We cannot build .proto files from other packages because the .pb.cc - # and .pb.h files would be written to that package, and we aren't allowed - # to write to other packages. - if self.context.local_filename(src) is None: - raise sebs.DefinitionError( - "Source file is not in this package: %s" % src) - - cc_artifact = self.context.derived_artifact(src, ".pb.cc", protoc_action) - header_artifact = self.context.derived_artifact( - src, ".pb.h", protoc_action) - - cpp_srcs.append(cc_artifact) - cpp_srcs.append(header_artifact) - - protoc_action.set_command( - sebs.SubprocessCommand(protoc_action, protoc_args, implicit = cpp_srcs)) - - deps = list(args.deps) - if args.lite: - deps.append(protobuf_lite) - else: - deps.append(protobuf) - - self.__cpp_library = _cpp.Library(srcs = cpp_srcs, deps = deps, - context = self.context) - self.__cpp_library.label = self.label - self.outputs = [] - - def as_cpp_library(self): - self.expand_once() - return self.__cpp_library - -# ==================================================================== -# Tests - -_lite_test_protos = ProtobufLibrary( - srcs = [ "unittest_lite.proto", - "unittest_import_lite.proto" ], - lite = True) -_test_protos = ProtobufLibrary( - srcs = [ "unittest.proto", - "unittest_empty.proto", - "unittest_import.proto", - "unittest_mset.proto", - "unittest_optimize_for.proto", - "unittest_embed_optimize_for.proto", - "unittest_custom_options.proto", - "unittest_lite_imports_nonlite.proto", - "compiler/cpp/cpp_test_bad_identifiers.proto" ], - deps = [ _lite_test_protos ]) - -_test_util = _cpp.Library( - name = "test_util", - srcs = [ "test_util.cc", - "test_util.h", - "testing/googletest.cc", - "testing/googletest.h", - "testing/file.cc", - "testing/file.h" ], - deps = [ protobuf, _test_protos, _cpp.SystemLibrary(name = "gtest")] ) - -protobuf_lite_test = _cpp.Test( - srcs = [ "lite_unittest.cc", - "test_util_lite.cc", - "test_util_lite.h" ], - deps = [ _lite_test_protos ]) - -protobuf_test = _cpp.Test( - srcs = [ "stubs/common_unittest.cc", - "stubs/once_unittest.cc", - "stubs/strutil_unittest.cc", - "stubs/structurally_valid_unittest.cc", - "descriptor_database_unittest.cc", - "descriptor_unittest.cc", - "dynamic_message_unittest.cc", - "extension_set_unittest.cc", - "generated_message_reflection_unittest.cc", - "message_unittest.cc", - "reflection_ops_unittest.cc", - "repeated_field_unittest.cc", - "text_format_unittest.cc", - "unknown_field_set_unittest.cc", - "wire_format_unittest.cc", - "io/coded_stream_unittest.cc", - "io/printer_unittest.cc", - "io/tokenizer_unittest.cc", - "io/zero_copy_stream_unittest.cc", - "compiler/command_line_interface_unittest.cc", - "compiler/importer_unittest.cc", - "compiler/parser_unittest.cc", - "compiler/cpp/cpp_bootstrap_unittest.cc", - "compiler/cpp/cpp_unittest.cc" ], - deps = [ protobuf, libprotoc, _test_util, - _cpp.SystemLibrary(name = "gtest_main") ]) diff --git a/src/google/protobuf/any.proto b/src/google/protobuf/any.proto new file mode 100644 index 00000000..0bb375ce --- /dev/null +++ b/src/google/protobuf/any.proto @@ -0,0 +1,103 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +syntax = "proto3"; + +package google.protobuf; + +option java_generate_equals_and_hash = true; +option java_multiple_files = true; +option java_outer_classname = "AnyProto"; +option java_package = "com.google.protobuf"; +option objc_class_prefix = "GPB"; + + +// `Any` contains an arbitrary serialized message along with a URL +// that describes the type of the serialized message. +// +// The proto runtimes and/or compiler will eventually +// provide utilities to pack/unpack Any values (projected Q1/15). +// +// # JSON +// The JSON representation of an `Any` value uses the regular +// representation of the deserialized, embedded message, with an +// additional field `@type` which contains the type URL. Example: +// +// package google.profile; +// message Person { +// string first_name = 1; +// string last_name = 2; +// } +// +// { +// "@type": "type.googleapis.com/google.profile.Person", +// "firstName": <string>, +// "lastName": <string> +// } +// +// If the embedded message type is well-known and has a custom JSON +// representation, that representation will be embedded adding a field +// `value` which holds the custom JSON in addition to the the `@type` +// field. Example (for message [google.protobuf.Duration][google.protobuf.Duration]): +// +// { +// "@type": "type.googleapis.com/google.protobuf.Duration", +// "value": "1.212s" +// } +// +message Any { + // A URL/resource name whose content describes the type of the + // serialized message. + // + // For URLs which use the schema `http`, `https`, or no schema, the + // following restrictions and interpretations apply: + // + // * If no schema is provided, `https` is assumed. + // * The last segment of the URL's path must represent the fully + // qualified name of the type (as in `path/google.protobuf.Duration`). + // * An HTTP GET on the URL must yield a [google.protobuf.Type][google.protobuf.Type] + // value in binary format, or produce an error. + // * Applications are allowed to cache lookup results based on the + // URL, or have them precompiled into a binary to avoid any + // lookup. Therefore, binary compatibility needs to be preserved + // on changes to types. (Use versioned type names to manage + // breaking changes.) + // + // Schemas other than `http`, `https` (or the empty schema) might be + // used with implementation specific semantics. + // + // Types originating from the `google.*` package + // namespace should use `type.googleapis.com/full.type.name` (without + // schema and path). A type service will eventually become available which + // serves those URLs (projected Q2/15). + string type_url = 1; + + // Must be valid serialized data of the above specified type. + bytes value = 2; +} diff --git a/src/google/protobuf/api.proto b/src/google/protobuf/api.proto new file mode 100644 index 00000000..f368c24d --- /dev/null +++ b/src/google/protobuf/api.proto @@ -0,0 +1,105 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +syntax = "proto3"; + +package google.protobuf; + +import "google/protobuf/source_context.proto"; +import "google/protobuf/type.proto"; + +option java_multiple_files = true; +option java_outer_classname = "ApiProto"; +option java_package = "com.google.protobuf"; +option objc_class_prefix = "GPB"; + + +// Api is a light-weight descriptor for a protocol buffer service. +message Api { + // The fully qualified name of this api, including package name + // followed by the api's simple name. + string name = 1; + + // The methods of this api, in unspecified order. + repeated Method methods = 2; + + // Any metadata attached to the API. + repeated Option options = 3; + + // A version string for this api. If specified, must have the form + // `major-version.minor-version`, as in `1.10`. If the minor version + // is omitted, it defaults to zero. If the entire version field is + // empty, the major version is derived from the package name, as + // outlined below. If the field is not empty, the version in the + // package name will be verified to be consistent with what is + // provided here. + // + // The versioning schema uses [semantic + // versioning](http://semver.org) where the major version number + // indicates a breaking change and the minor version an additive, + // non-breaking change. Both version numbers are signals to users + // what to expect from different versions, and should be carefully + // chosen based on the product plan. + // + // The major version is also reflected in the package name of the + // API, which must end in `v<major-version>`, as in + // `google.feature.v1`. For major versions 0 and 1, the suffix can + // be omitted. Zero major versions must only be used for + // experimental, none-GA apis. + // + // See also: [design doc](http://go/api-versioning). + // + // + string version = 4; + + // Source context for the protocol buffer service represented by this + // message. + SourceContext source_context = 5; +} + +// Method represents a method of an api. +message Method { + // The simple name of this method. + string name = 1; + + // A URL of the input message type. + string request_type_url = 2; + + // If true, the request is streamed. + bool request_streaming = 3; + + // The URL of the output message type. + string response_type_url = 4; + + // If true, the response is streamed. + bool response_streaming = 5; + + // Any metadata attached to the method. + repeated Option options = 6; +} diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc index be0d9e34..bda37413 100644..100755 --- a/src/google/protobuf/arena.cc +++ b/src/google/protobuf/arena.cc @@ -38,37 +38,62 @@ namespace google { namespace protobuf { google::protobuf::internal::SequenceNumber Arena::lifecycle_id_generator_; -__thread Arena::ThreadCache Arena::thread_cache_ = { -1, NULL }; +#ifdef PROTOBUF_USE_DLLS +Arena::ThreadCache& Arena::thread_cache() { + static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL }; + return thread_cache_; +} +#else +GOOGLE_THREAD_LOCAL Arena::ThreadCache Arena::thread_cache_ = { -1, NULL }; +#endif -void Arena::Init(const ArenaOptions& options) { +void Arena::Init() { lifecycle_id_ = lifecycle_id_generator_.GetNext(); - start_block_size_ = options.start_block_size; - max_block_size_ = options.max_block_size; - block_alloc = options.block_alloc; - block_dealloc = options.block_dealloc; - blocks_ = NULL; - hint_ = NULL; + blocks_ = 0; + hint_ = 0; owns_first_block_ = true; - cleanup_list_ = NULL; + cleanup_list_ = 0; - if (options.initial_block != NULL && options.initial_block_size > 0) { + if (options_.initial_block != NULL && options_.initial_block_size > 0) { // Add first unowned block to list. - Block* first_block = reinterpret_cast<Block*>(options.initial_block); - first_block->size = options.initial_block_size; + Block* first_block = reinterpret_cast<Block*>(options_.initial_block); + first_block->size = options_.initial_block_size; first_block->pos = kHeaderSize; first_block->next = NULL; first_block->owner = &first_block->owner; AddBlock(first_block); owns_first_block_ = false; } + + // Call the initialization hook + if (options_.on_arena_init != NULL) { + hooks_cookie_ = options_.on_arena_init(this); + } else { + hooks_cookie_ = NULL; + } +} + +Arena::~Arena() { + uint64 space_allocated = Reset(); + + // Call the destruction hook + if (options_.on_arena_destruction != NULL) { + options_.on_arena_destruction(this, hooks_cookie_, space_allocated); + } } uint64 Arena::Reset() { CleanupList(); - uint64 space_used = FreeBlocks(); + uint64 space_allocated = FreeBlocks(); // Invalidate any ThreadCaches pointing to any blocks we just destroyed. lifecycle_id_ = lifecycle_id_generator_.GetNext(); - return space_used; + + // Call the reset hook + if (options_.on_arena_reset != NULL) { + options_.on_arena_reset(this, hooks_cookie_, space_allocated); + } + + return space_allocated; } Arena::Block* Arena::NewBlock(void* me, Block* my_last_block, size_t n, @@ -86,7 +111,7 @@ Arena::Block* Arena::NewBlock(void* me, Block* my_last_block, size_t n, size = kHeaderSize + n; } - Block* b = reinterpret_cast<Block*>(block_alloc(size)); + Block* b = reinterpret_cast<Block*>(options_.block_alloc(size)); b->pos = kHeaderSize + n; b->size = size; if (b->avail() == 0) { @@ -130,18 +155,18 @@ void* Arena::AllocateAligned(size_t n) { // If this thread already owns a block in this arena then try to use that. // This fast path optimizes the case where multiple threads allocate from the // same arena. - if (thread_cache_.last_lifecycle_id_seen == lifecycle_id_ && - thread_cache_.last_block_used_ != NULL) { - if (thread_cache_.last_block_used_->avail() < n) { + if (thread_cache().last_lifecycle_id_seen == lifecycle_id_ && + thread_cache().last_block_used_ != NULL) { + if (thread_cache().last_block_used_->avail() < n) { return SlowAlloc(n); } - return AllocFromBlock(thread_cache_.last_block_used_, n); + return AllocFromBlock(thread_cache().last_block_used_, n); } // Check whether we own the last accessed block on this arena. // This fast path optimizes the case where a single thread uses multiple // arenas. - void* me = &thread_cache_; + void* me = &thread_cache(); Block* b = reinterpret_cast<Block*>(google::protobuf::internal::Acquire_Load(&hint_)); if (!b || b->owner != me || b->avail() < n) { // If the next block to allocate from is the first block, try to claim it @@ -169,7 +194,7 @@ void* Arena::AllocFromBlock(Block* b, size_t n) { } void* Arena::SlowAlloc(size_t n) { - void* me = &thread_cache_; + void* me = &thread_cache(); Block* b = FindBlock(me); // Find block owned by me. // See if allocation fits in my latest block. if (b != NULL && b->avail() >= n) { @@ -177,7 +202,7 @@ void* Arena::SlowAlloc(size_t n) { google::protobuf::internal::NoBarrier_Store(&hint_, reinterpret_cast<google::protobuf::internal::AtomicWord>(b)); return AllocFromBlock(b, n); } - b = NewBlock(me, b, n, start_block_size_, max_block_size_); + b = NewBlock(me, b, n, options_.start_block_size, options_.max_block_size); AddBlock(b); if (b->owner == me) { // If this block can be reused (see NewBlock()). SetThreadCacheBlock(b); @@ -185,29 +210,38 @@ void* Arena::SlowAlloc(size_t n) { return reinterpret_cast<char*>(b) + kHeaderSize; } +uint64 Arena::SpaceAllocated() const { + uint64 space_allocated = 0; + Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_)); + while (b != NULL) { + space_allocated += (b->size); + b = b->next; + } + return space_allocated; +} + uint64 Arena::SpaceUsed() const { uint64 space_used = 0; Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_)); while (b != NULL) { - space_used += (b->size); + space_used += (b->pos - kHeaderSize); b = b->next; } return space_used; } - uint64 Arena::FreeBlocks() { - uint64 space_used = 0; + uint64 space_allocated = 0; Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_)); Block* first_block = NULL; while (b != NULL) { - space_used += (b->size); + space_allocated += (b->size); Block* next = b->next; if (next != NULL) { - block_dealloc(b, b->size); + options_.block_dealloc(b, b->size); } else { if (owns_first_block_) { - block_dealloc(b, b->size); + options_.block_dealloc(b, b->size); } else { // User passed in the first block, skip free'ing the memory. first_block = b; @@ -224,7 +258,7 @@ uint64 Arena::FreeBlocks() { first_block->owner = &first_block->owner; AddBlock(first_block); } - return space_used; + return space_allocated; } void Arena::CleanupList() { diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index 519e3569..bb15e80c 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h @@ -34,9 +34,11 @@ #ifndef GOOGLE_PROTOBUF_ARENA_H__ #define GOOGLE_PROTOBUF_ARENA_H__ -#include <google/protobuf/stubs/common.h> +#include <typeinfo> + #include <google/protobuf/stubs/atomic_sequence_num.h> #include <google/protobuf/stubs/atomicops.h> +#include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/type_traits.h> namespace google { @@ -89,19 +91,44 @@ struct ArenaOptions { // A function pointer to an alloc method that returns memory blocks of size // requested. By default, it contains a ptr to the malloc function. + // + // NOTE: block_alloc and dealloc functions are expected to behave like + // malloc and free, including Asan poisoning. void* (*block_alloc)(size_t); // A function pointer to a dealloc method that takes ownership of the blocks // from the arena. By default, it contains a ptr to a wrapper function that // calls free. void (*block_dealloc)(void*, size_t); + // Hooks for adding external functionality such as user-specific metrics + // collection, specific debugging abilities, etc. + // Init hook may return a pointer to a cookie to be stored in the arena. + // reset and destruction hooks will then be called with the same cookie + // pointer. This allows us to save an external object per arena instance and + // use it on the other hooks (Note: It is just as legal for init to return + // NULL and not use the cookie feature). + // on_arena_reset and on_arena_destruction also receive the space used in + // the arena just before the reset. + void* (*on_arena_init)(Arena* arena); + void (*on_arena_reset)(Arena* arena, void* cookie, uint64 space_used); + void (*on_arena_destruction)(Arena* arena, void* cookie, uint64 space_used); + + // type_name is promised to be a static string - its lifetime extends to + // match program's lifetime. + void (*on_arena_allocation)(const char* type_name, uint64 alloc_size, + Arena* arena, void* cookie); + ArenaOptions() : start_block_size(kDefaultStartBlockSize), max_block_size(kDefaultMaxBlockSize), initial_block(NULL), initial_block_size(0), block_alloc(&malloc), - block_dealloc(&internal::arena_free) {} + block_dealloc(&internal::arena_free), + on_arena_init(NULL), + on_arena_reset(NULL), + on_arena_destruction(NULL), + on_arena_allocation(NULL) {} private: // Constants define default starting block size and max block size for @@ -123,23 +150,21 @@ class LIBPROTOBUF_EXPORT Arena { public: // Arena constructor taking custom options. See ArenaOptions below for // descriptions of the options available. - explicit Arena(const ArenaOptions& options) { - Init(options); + explicit Arena(const ArenaOptions& options) : options_(options) { + Init(); } // Default constructor with sensible default options, tuned for average // use-cases. Arena() { - Init(ArenaOptions()); + Init(); } // Destructor deletes all owned heap allocated objects, and destructs objects // that have non-trivial destructors, except for proto2 message objects whose // destructors can be skipped. Also, frees all blocks except the initial block // if it was passed in. - ~Arena() { - Reset(); - } + ~Arena(); // API to create proto2 message objects on the arena. If the arena passed in // is NULL, then a heap allocated object is returned. Type T must be a message @@ -195,6 +220,40 @@ class LIBPROTOBUF_EXPORT Arena { } } + // Version of the above with three constructor arguments for the created + // object. + template <typename T, typename Arg1, typename Arg2, typename Arg3> + GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena, + const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3) { + if (arena == NULL) { + return new T(arg1, arg2, arg3); + } else { + return arena->CreateInternal<T>(SkipDeleteList<T>(static_cast<T*>(0)), + arg1, + arg2, + arg3); + } + } + + // Version of the above with four constructor arguments for the created + // object. + template <typename T, typename Arg1, typename Arg2, typename Arg3, + typename Arg4> + GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena, + const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4) { + if (arena == NULL) { + return new T(arg1, arg2, arg3, arg4); + } else { + return arena->CreateInternal<T>(SkipDeleteList<T>(static_cast<T*>(0)), + arg1, + arg2, + arg3, + arg4); + } + } + // Create an array of object type T on the arena. Type T must have a trivial // constructor, as it will not be invoked when created on the arena. template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE @@ -202,8 +261,7 @@ class LIBPROTOBUF_EXPORT Arena { if (arena == NULL) { return new T[num_elements]; } else { - return static_cast<T*>( - arena->AllocateAligned(num_elements * sizeof(T))); + return arena->CreateInternalRawArray<T>(num_elements); } } @@ -211,6 +269,8 @@ class LIBPROTOBUF_EXPORT Arena { // of the underlying blocks. The total space used may not include the new // blocks that are allocated by this arena from other threads concurrently // with the call to this method. + uint64 SpaceAllocated() const GOOGLE_ATTRIBUTE_NOINLINE; + // As above, but does not include any free space in underlying blocks. uint64 SpaceUsed() const GOOGLE_ATTRIBUTE_NOINLINE; // Frees all storage allocated by this arena after calling destructors @@ -253,7 +313,7 @@ class LIBPROTOBUF_EXPORT Arena { // latter is a virtual call, while this method is a templated call that // resolves at compile-time. template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE - static inline ::google::protobuf::Arena* GetArena(T* value) { + static inline ::google::protobuf::Arena* GetArena(const T* value) { return GetArenaInternal(value, static_cast<T*>(0)); } @@ -295,9 +355,6 @@ class LIBPROTOBUF_EXPORT Arena { // data follows }; - void* (*block_alloc)(size_t); // Allocates a free block of a particular size. - void (*block_dealloc)(void*, size_t); // Deallocates the given block. - template<typename Type> friend class ::google::protobuf::internal::GenericTypeHandler; friend class MockArena; // For unit-testing. friend class internal::ArenaString; // For AllocateAligned. @@ -312,7 +369,14 @@ class LIBPROTOBUF_EXPORT Arena { static const size_t kHeaderSize = sizeof(Block); static google::protobuf::internal::SequenceNumber lifecycle_id_generator_; - static __thread ThreadCache thread_cache_; +#ifdef PROTOBUF_USE_DLLS + // Thread local variables cannot be exposed through DLL interface but we can + // wrap them in static functions. + static ThreadCache& thread_cache(); +#else + static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_; + static ThreadCache& thread_cache() { return thread_cache_; } +#endif // SFINAE for skipping addition to delete list for a Type. This is mainly to // skip proto2/proto1 message objects with cc_enable_arenas=true from being @@ -347,6 +411,13 @@ class LIBPROTOBUF_EXPORT Arena { return Create<T>(arena); } + // Just allocate the required size for the given type assuming the + // type has a trivial constructor. + template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE + inline T* CreateInternalRawArray(uint32 num_elements) { + return static_cast<T*>(AllocateAligned(sizeof(T) * num_elements)); + } + template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal( bool skip_explicit_ownership) { @@ -377,12 +448,57 @@ class LIBPROTOBUF_EXPORT Arena { return t; } + template <typename T, typename Arg1, typename Arg2, typename Arg3> + GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership, + const Arg1& arg1, + const Arg2& arg2, + const Arg3& arg3) { + T* t = new (AllocateAligned(sizeof(T))) T(arg1, arg2, arg3); + if (!skip_explicit_ownership) { + AddListNode(t, &internal::arena_destruct_object<T>); + } + return t; + } + + template <typename T, typename Arg1, typename Arg2, typename Arg3, + typename Arg4> + GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership, + const Arg1& arg1, + const Arg2& arg2, + const Arg3& arg3, + const Arg4& arg4) { + T* t = new (AllocateAligned(sizeof(T))) T(arg1, arg2, arg3, arg4); + if (!skip_explicit_ownership) { + AddListNode(t, &internal::arena_destruct_object<T>); + } + return t; + } + template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*) { return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)), this); } + // CreateInArenaStorage is used to implement map field. Without it, + // google::protobuf::Map need to call generated message's protected arena constructor, + // which needs to declare google::protobuf::Map as friend of generated message. + template <typename T> + static void CreateInArenaStorage(T* ptr, Arena* arena) { + CreateInArenaStorageInternal(ptr, arena, is_arena_constructable<T>::value); + } + template <typename T> + static void CreateInArenaStorageInternal( + T* ptr, Arena* arena, google::protobuf::internal::true_type) { + new (ptr) T(arena); + } + + template <typename T> + static void CreateInArenaStorageInternal( + T* ptr, Arena* arena, google::protobuf::internal::false_type) { + new (ptr) T; + } + // These implement Own(), which registers an object for deletion (destructor // call and operator delete()). The second parameter has type 'true_type' if T // is a subtype of ::google::protobuf::Message and 'false_type' otherwise. Collapsing @@ -405,20 +521,20 @@ class LIBPROTOBUF_EXPORT Arena { // InternalArenaConstructable_ tags can be associated with an arena, and such // objects must implement a GetArenaNoVirtual() method. template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE - static inline ::google::protobuf::Arena* GetArenaInternal(T* value, + static inline ::google::protobuf::Arena* GetArenaInternal(const T* value, typename T::InternalArenaConstructable_*) { return value->GetArenaNoVirtual(); } template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE - static inline ::google::protobuf::Arena* GetArenaInternal(T* value, ...) { + static inline ::google::protobuf::Arena* GetArenaInternal(const T* value, ...) { return NULL; } void* AllocateAligned(size_t size); - void Init(const ArenaOptions& options); + void Init(); // Free all blocks and return the total space used which is the sums of sizes // of the all the allocated blocks. @@ -434,13 +550,11 @@ class LIBPROTOBUF_EXPORT Arena { void CleanupList(); inline void SetThreadCacheBlock(Block* block) { - thread_cache_.last_block_used_ = block; - thread_cache_.last_lifecycle_id_seen = lifecycle_id_; + thread_cache().last_block_used_ = block; + thread_cache().last_lifecycle_id_seen = lifecycle_id_; } int64 lifecycle_id_; // Unique for each arena. Changes on Reset(). - size_t start_block_size_; // Starting block size of the arena. - size_t max_block_size_; // Max block size of the arena. google::protobuf::internal::AtomicWord blocks_; // Head of linked list of all allocated blocks google::protobuf::internal::AtomicWord hint_; // Fast thread-local block access @@ -465,6 +579,15 @@ class LIBPROTOBUF_EXPORT Arena { Block* NewBlock(void* me, Block* my_last_block, size_t n, size_t start_block_size, size_t max_block_size); static void* AllocFromBlock(Block* b, size_t n); + template <typename Key, typename T> + friend class Map; + + // The arena may save a cookie it receives from the external on_init hook + // and then use it when calling the on_reset and on_destruction hooks. + void* hooks_cookie_; + + ArenaOptions options_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Arena); }; diff --git a/src/google/protobuf/arena_nc_test.py b/src/google/protobuf/arena_nc_test.py index 41b1b5f8..f390df36 100644 --- a/src/google/protobuf/arena_nc_test.py +++ b/src/google/protobuf/arena_nc_test.py @@ -1,4 +1,4 @@ -#! /usr/bin/python +#! /usr/bin/env python # # Protocol Buffers - Google's data interchange format # Copyright 2008 Google Inc. All rights reserved. @@ -32,11 +32,12 @@ """Negative compilation unit tests for arena API.""" +import unittest + from google3.testing.pybase import fake_target_util -from google.apputils import basetest -class ArenaNcTest(basetest.TestCase): +class ArenaNcTest(unittest.TestCase): def testCompilerErrors(self): """Runs a list of tests to verify compiler error messages.""" @@ -56,4 +57,4 @@ class ArenaNcTest(basetest.TestCase): ) if __name__ == '__main__': - basetest.main() + unittest.main() diff --git a/src/google/protobuf/arena_test_util.cc b/src/google/protobuf/arena_test_util.cc new file mode 100644 index 00000000..21f55c6e --- /dev/null +++ b/src/google/protobuf/arena_test_util.cc @@ -0,0 +1,49 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/arena_test_util.h> + + +#define EXPECT_EQ GOOGLE_CHECK_EQ + +namespace google { +namespace protobuf { +namespace internal { + +NoHeapChecker::~NoHeapChecker() { + capture_alloc.Unhook(); + EXPECT_EQ(0, capture_alloc.alloc_count()); + EXPECT_EQ(0, capture_alloc.free_count()); +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/arena_test_util.h b/src/google/protobuf/arena_test_util.h new file mode 100644 index 00000000..7db7a90e --- /dev/null +++ b/src/google/protobuf/arena_test_util.h @@ -0,0 +1,59 @@ +// 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_ARENA_TEST_UTIL_H__ +#define GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__ + +namespace google { +namespace protobuf { +namespace internal { + +class NoHeapChecker { + public: + NoHeapChecker() { + capture_alloc.Hook(); + } + ~NoHeapChecker(); + private: + class NewDeleteCapture { + public: + // TOOD(xiaofeng): Implement this for opensource protobuf. + void Hook() {} + void Unhook() {} + int alloc_count() { return 0; } + int free_count() { return 0; } + } capture_alloc; +}; + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__ diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc index 76a4274f..d9b198e0 100644 --- a/src/google/protobuf/arena_unittest.cc +++ b/src/google/protobuf/arena_unittest.cc @@ -30,6 +30,8 @@ #include <google/protobuf/arena.h> +#include <stdint.h> + #include <algorithm> #include <cstring> #include <memory> @@ -40,6 +42,7 @@ #include <vector> #include <google/protobuf/stubs/common.h> +#include <google/protobuf/arena_test_util.h> #include <google/protobuf/test_util.h> #include <google/protobuf/unittest.pb.h> #include <google/protobuf/unittest_arena.pb.h> @@ -91,6 +94,37 @@ class SimpleDataType { private: Notifier* notifier_; }; + +// A simple class that does not allow copying and so cannot be used as a +// parameter type without "const &". +class PleaseDontCopyMe { + public: + explicit PleaseDontCopyMe(int value) : value_(value) {} + + int value() const { return value_; } + + private: + int value_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PleaseDontCopyMe); +}; + +// A class that takes four different types as constructor arguments. +class MustBeConstructedWithOneThroughFour { + public: + MustBeConstructedWithOneThroughFour( + int one, const char* two, const string& three, + const PleaseDontCopyMe* four) + : one_(one), two_(two), three_(three), four_(four) {} + + int one_; + const char* const two_; + string three_; + const PleaseDontCopyMe* four_; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MustBeConstructedWithOneThroughFour); +}; + } // namespace TEST(ArenaTest, ArenaConstructable) { @@ -122,13 +156,27 @@ TEST(ArenaTest, BasicCreate) { EXPECT_EQ(2, notifier.GetCount()); } +TEST(ArenaTest, CreateWithManyConstructorArguments) { + Arena arena; + const string three("3"); + const PleaseDontCopyMe four(4); + const MustBeConstructedWithOneThroughFour* new_object = + Arena::Create<MustBeConstructedWithOneThroughFour>( + &arena, 1, "2", three, &four); + EXPECT_TRUE(new_object != NULL); + ASSERT_EQ(1, new_object->one_); + ASSERT_STREQ("2", new_object->two_); + ASSERT_EQ("3", new_object->three_); + ASSERT_EQ(4, new_object->four_->value()); +} + TEST(ArenaTest, InitialBlockTooSmall) { // Construct a small (64 byte) initial block of memory to be used by the // arena allocator; then, allocate an object which will not fit in the // initial block. std::vector<char> arena_block(64); ArenaOptions options; - options.initial_block = arena_block.data(); + options.initial_block = &arena_block[0]; options.initial_block_size = arena_block.size(); Arena arena(options); @@ -137,7 +185,7 @@ TEST(ArenaTest, InitialBlockTooSmall) { // Ensure that the arena allocator did not return memory pointing into the // initial block of memory. - uintptr_t arena_start = reinterpret_cast<uintptr_t>(arena_block.data()); + uintptr_t arena_start = reinterpret_cast<uintptr_t>(&arena_block[0]); uintptr_t arena_end = arena_start + arena_block.size(); EXPECT_FALSE(allocation >= arena_start && allocation < arena_end); @@ -380,6 +428,7 @@ TEST(ArenaTest, ReleaseFromArenaMessageMakesCopy) { delete nested_string; } +#ifndef GOOGLE_PROTOBUF_NO_RTTI TEST(ArenaTest, ReleaseFromArenaMessageUsingReflectionMakesCopy) { TestAllTypes::NestedMessage* nested_msg = NULL; // Note: no string: reflection API only supports releasing submessages. @@ -390,12 +439,13 @@ TEST(ArenaTest, ReleaseFromArenaMessageUsingReflectionMakesCopy) { const Reflection* r = arena_message->GetReflection(); const FieldDescriptor* f = arena_message->GetDescriptor()->FindFieldByName( "optional_nested_message"); - nested_msg = dynamic_cast<TestAllTypes::NestedMessage*>( + nested_msg = static_cast<TestAllTypes::NestedMessage*>( r->ReleaseMessage(arena_message, f)); } EXPECT_EQ(42, nested_msg->bb()); delete nested_msg; } +#endif // !GOOGLE_PROTOBUF_NO_RTTI TEST(ArenaTest, UnsafeArenaReleaseDoesNotMakeCopy) { Arena arena; @@ -671,6 +721,57 @@ TEST(ArenaTest, UnsafeArenaAddAllocated) { } } +TEST(ArenaTest, UnsafeArenaRelease) { + Arena arena; + TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena); + + string* s = new string("test string"); + message->unsafe_arena_set_allocated_optional_string(s); + EXPECT_TRUE(message->has_optional_string()); + EXPECT_EQ("test string", message->optional_string()); + s = message->unsafe_arena_release_optional_string(); + EXPECT_FALSE(message->has_optional_string()); + delete s; + + s = new string("test string"); + message->unsafe_arena_set_allocated_oneof_string(s); + EXPECT_TRUE(message->has_oneof_string()); + EXPECT_EQ("test string", message->oneof_string()); + s = message->unsafe_arena_release_oneof_string(); + EXPECT_FALSE(message->has_oneof_string()); + delete s; +} + +TEST(ArenaTest, ArenaOneofReflection) { + Arena arena; + TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena); + const Descriptor* desc = message->GetDescriptor(); + const Reflection* refl = message->GetReflection(); + + const FieldDescriptor* string_field = desc->FindFieldByName( + "oneof_string"); + const FieldDescriptor* msg_field = desc->FindFieldByName( + "oneof_nested_message"); + const OneofDescriptor* oneof = desc->FindOneofByName( + "oneof_field"); + + refl->SetString(message, string_field, "Test value"); + EXPECT_TRUE(refl->HasOneof(*message, oneof)); + refl->ClearOneof(message, oneof); + EXPECT_FALSE(refl->HasOneof(*message, oneof)); + + Message* submsg = refl->MutableMessage(message, msg_field); + EXPECT_TRUE(refl->HasOneof(*message, oneof)); + refl->ClearOneof(message, oneof); + EXPECT_FALSE(refl->HasOneof(*message, oneof)); + refl->MutableMessage(message, msg_field); + EXPECT_TRUE(refl->HasOneof(*message, oneof)); + submsg = refl->ReleaseMessage(message, msg_field); + EXPECT_FALSE(refl->HasOneof(*message, oneof)); + EXPECT_TRUE(submsg->GetArena() == NULL); + delete submsg; +} + namespace { void TestSwapRepeatedField(Arena* arena1, Arena* arena2) { // Test "safe" (copying) semantics for direct Swap() on RepeatedPtrField @@ -746,37 +847,16 @@ TEST(ArenaTest, ExtensionsOnArena) { protobuf_unittest::optional_nested_message_extension)->set_bb(42); } -class NoHeapChecker { - public: - NoHeapChecker() { - capture_alloc.Hook(); - } - ~NoHeapChecker() { - capture_alloc.Unhook(); - EXPECT_EQ(0, capture_alloc.alloc_count()); - EXPECT_EQ(0, capture_alloc.free_count()); - } - private: - class NewDeleteCapture { - public: - // TOOD(xiaofeng): Implement this for opensource protobuf. - void Hook() {} - void Unhook() {} - int alloc_count() { return 0; } - int free_count() { return 0; } - } capture_alloc; -}; - TEST(ArenaTest, RepeatedFieldOnArena) { // Preallocate an initial arena block to avoid mallocs during hooked region. std::vector<char> arena_block(1024 * 1024); ArenaOptions options; - options.initial_block = arena_block.data(); + options.initial_block = &arena_block[0]; options.initial_block_size = arena_block.size(); Arena arena(options); { - NoHeapChecker no_heap; + internal::NoHeapChecker no_heap; // Fill some repeated fields on the arena to test for leaks. Also verify no // memory allocations. @@ -846,6 +926,7 @@ TEST(ArenaTest, RepeatedFieldOnArena) { } +#ifndef GOOGLE_PROTOBUF_NO_RTTI TEST(ArenaTest, MutableMessageReflection) { Arena arena; TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena); @@ -853,7 +934,7 @@ TEST(ArenaTest, MutableMessageReflection) { const Descriptor* d = message->GetDescriptor(); const FieldDescriptor* field = d->FindFieldByName("optional_nested_message"); TestAllTypes::NestedMessage* submessage = - dynamic_cast<TestAllTypes::NestedMessage*>( + static_cast<TestAllTypes::NestedMessage*>( r->MutableMessage(message, field)); TestAllTypes::NestedMessage* submessage_expected = message->mutable_optional_nested_message(); @@ -862,13 +943,14 @@ TEST(ArenaTest, MutableMessageReflection) { EXPECT_EQ(&arena, submessage->GetArena()); const FieldDescriptor* oneof_field = d->FindFieldByName("oneof_nested_message"); - submessage = dynamic_cast<TestAllTypes::NestedMessage*>( + submessage = static_cast<TestAllTypes::NestedMessage*>( r->MutableMessage(message, oneof_field)); submessage_expected = message->mutable_oneof_nested_message(); EXPECT_EQ(submessage_expected, submessage); EXPECT_EQ(&arena, submessage->GetArena()); } +#endif // !GOOGLE_PROTOBUF_NO_RTTI namespace { @@ -898,7 +980,7 @@ TEST(ArenaTest, NoHeapAllocationsTest) { // Allocate a large initial block to avoid mallocs during hooked test. std::vector<char> arena_block(128 * 1024); ArenaOptions options; - options.initial_block = arena_block.data(); + options.initial_block = &arena_block[0]; options.initial_block_size = arena_block.size(); Arena arena(options); @@ -911,18 +993,17 @@ TEST(ArenaTest, NoHeapAllocationsTest) { arena.Reset(); } - +#ifndef GOOGLE_PROTOBUF_NO_RTTI // Test construction on an arena via generic MessageLite interface. We should be // able to successfully deserialize on the arena without incurring heap // allocations, i.e., everything should still be arena-allocation-aware. TEST(ArenaTest, MessageLiteOnArena) { std::vector<char> arena_block(128 * 1024); ArenaOptions options; - options.initial_block = arena_block.data(); + options.initial_block = &arena_block[0]; options.initial_block_size = arena_block.size(); Arena arena(options); - const google::protobuf::MessageLite* prototype = dynamic_cast< - const google::protobuf::MessageLite*>(&TestAllTypes::default_instance()); + const google::protobuf::MessageLite* prototype = &TestAllTypes::default_instance(); TestAllTypes initial_message; FillArenaAwareFields(&initial_message); @@ -935,13 +1016,13 @@ TEST(ArenaTest, MessageLiteOnArena) { EXPECT_TRUE(generic_message != NULL); EXPECT_EQ(&arena, generic_message->GetArena()); EXPECT_TRUE(generic_message->ParseFromString(serialized)); - TestAllTypes* deserialized = dynamic_cast<TestAllTypes*>(generic_message); - EXPECT_TRUE(deserialized != NULL); + TestAllTypes* deserialized = static_cast<TestAllTypes*>(generic_message); EXPECT_EQ(42, deserialized->optional_int32()); } arena.Reset(); } +#endif // !GOOGLE_PROTOBUF_NO_RTTI // RepeatedField should support non-POD types, and invoke constructors and @@ -963,37 +1044,49 @@ TEST(ArenaTest, RepeatedFieldWithNonPODType) { } } -TEST(ArenaTest, SpaceUsed) { +// Align n to next multiple of 8 +namespace { +uint64 Align8(uint64 n) { return (n + 7) & -8; } +} // namespace + +TEST(ArenaTest, SpaceAllocated_and_Used) { ArenaOptions options; options.start_block_size = 256; options.max_block_size = 8192; Arena arena_1(options); + EXPECT_EQ(0, arena_1.SpaceAllocated()); EXPECT_EQ(0, arena_1.SpaceUsed()); EXPECT_EQ(0, arena_1.Reset()); ::google::protobuf::Arena::CreateArray<char>(&arena_1, 320); // Arena will allocate slightly more than 320 for the block headers. - EXPECT_LE(320, arena_1.SpaceUsed()); + EXPECT_LE(320, arena_1.SpaceAllocated()); + EXPECT_EQ(Align8(320), arena_1.SpaceUsed()); EXPECT_LE(320, arena_1.Reset()); // Test with initial block. std::vector<char> arena_block(1024); - options.initial_block = arena_block.data(); + options.initial_block = &arena_block[0]; options.initial_block_size = arena_block.size(); Arena arena_2(options); - EXPECT_EQ(1024, arena_2.SpaceUsed()); + EXPECT_EQ(1024, arena_2.SpaceAllocated()); + EXPECT_EQ(0, arena_2.SpaceUsed()); EXPECT_EQ(1024, arena_2.Reset()); ::google::protobuf::Arena::CreateArray<char>(&arena_2, 55); - EXPECT_EQ(1024, arena_2.SpaceUsed()); + EXPECT_EQ(1024, arena_2.SpaceAllocated()); + EXPECT_EQ(Align8(55), arena_2.SpaceUsed()); EXPECT_EQ(1024, arena_2.Reset()); // Reset options to test doubling policy explicitly. options.initial_block = NULL; options.initial_block_size = 0; Arena arena_3(options); + EXPECT_EQ(0, arena_3.SpaceUsed()); ::google::protobuf::Arena::CreateArray<char>(&arena_3, 190); - EXPECT_EQ(256, arena_3.SpaceUsed()); + EXPECT_EQ(256, arena_3.SpaceAllocated()); + EXPECT_EQ(Align8(190), arena_3.SpaceUsed()); ::google::protobuf::Arena::CreateArray<char>(&arena_3, 70); - EXPECT_EQ(256 + 512, arena_3.SpaceUsed()); + EXPECT_EQ(256 + 512, arena_3.SpaceAllocated()); + EXPECT_EQ(Align8(190) + Align8(70), arena_3.SpaceUsed()); EXPECT_EQ(256 + 512, arena_3.Reset()); } @@ -1005,5 +1098,76 @@ TEST(ArenaTest, Alignment) { } } +TEST(ArenaTest, GetArenaShouldReturnTheArenaForArenaAllocatedMessages) { + ::google::protobuf::Arena arena; + ArenaMessage* message = Arena::CreateMessage<ArenaMessage>(&arena); + const ArenaMessage* const_pointer_to_message = message; + EXPECT_EQ(&arena, Arena::GetArena(message)); + EXPECT_EQ(&arena, Arena::GetArena(const_pointer_to_message)); +} + +TEST(ArenaTest, GetArenaShouldReturnNullForNonArenaAllocatedMessages) { + ArenaMessage message; + const ArenaMessage* const_pointer_to_message = &message; + EXPECT_EQ(NULL, Arena::GetArena(&message)); + EXPECT_EQ(NULL, Arena::GetArena(const_pointer_to_message)); +} + +// A helper utility class to only contain static hook functions, some +// counters to be used to verify the counters have been called and a cookie +// value to be verified. +class ArenaHooksTestUtil { + public: + static void* on_init(::google::protobuf::Arena* arena) { + ++num_init; + int* cookie = new int(kCookieValue); + return static_cast<void*>(cookie); + } + + static void on_reset(::google::protobuf::Arena* arena, void* cookie, + uint64 space_used) { + ++num_reset; + int cookie_value = *static_cast<int*>(cookie); + EXPECT_EQ(kCookieValue, cookie_value); + } + + static void on_destruction(::google::protobuf::Arena* arena, void* cookie, + uint64 space_used) { + ++num_destruct; + int cookie_value = *static_cast<int*>(cookie); + EXPECT_EQ(kCookieValue, cookie_value); + delete static_cast<int*>(cookie); + } + + static const int kCookieValue = 999; + static uint32 num_init; + static uint32 num_reset; + static uint32 num_destruct; +}; +uint32 ArenaHooksTestUtil::num_init = 0; +uint32 ArenaHooksTestUtil::num_reset = 0; +uint32 ArenaHooksTestUtil::num_destruct = 0; +const int ArenaHooksTestUtil::kCookieValue; + +// Test the hooks are correctly called and that the cookie is passed. +TEST(ArenaTest, ArenaHooksSanity) { + ::google::protobuf::ArenaOptions options; + options.on_arena_init = ArenaHooksTestUtil::on_init; + options.on_arena_reset = ArenaHooksTestUtil::on_reset; + options.on_arena_destruction = ArenaHooksTestUtil::on_destruction; + + // Scope for defining the arena + { + ::google::protobuf::Arena arena(options); + EXPECT_EQ(1, ArenaHooksTestUtil::num_init); + + arena.Reset(); + arena.Reset(); + EXPECT_EQ(2, ArenaHooksTestUtil::num_reset); + } + EXPECT_EQ(3, ArenaHooksTestUtil::num_reset); + EXPECT_EQ(1, ArenaHooksTestUtil::num_destruct); +} + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h index 50f13837..d829ed91 100755 --- a/src/google/protobuf/arenastring.h +++ b/src/google/protobuf/arenastring.h @@ -31,7 +31,6 @@ #ifndef GOOGLE_PROTOBUF_ARENASTRING_H__ #define GOOGLE_PROTOBUF_ARENASTRING_H__ -#include <stdint.h> #include <string> #include <google/protobuf/stubs/common.h> @@ -54,7 +53,7 @@ namespace google { namespace protobuf { namespace internal { -struct ArenaStringPtr { +struct LIBPROTOBUF_EXPORT ArenaStringPtr { inline void Set(const ::std::string* default_value, const ::std::string& value, ::google::protobuf::Arena* arena) { if (ptr_ == default_value) { diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 13250702..567238ae 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -48,7 +48,6 @@ #include <iostream> #include <ctype.h> -#include <google/protobuf/stubs/hash.h> #include <memory> #ifndef _SHARED_PTR_H #include <google/protobuf/stubs/shared_ptr.h> @@ -152,7 +151,7 @@ bool VerifyDirectoryExists(const string& path) { if (path.empty()) return true; if (access(path.c_str(), F_OK) == -1) { - cerr << path << ": " << strerror(errno) << endl; + std::cerr << path << ": " << strerror(errno) << std::endl; return false; } else { return true; @@ -171,8 +170,8 @@ bool TryCreateParentDirectory(const string& prefix, const string& filename) { path_so_far += parts[i]; if (mkdir(path_so_far.c_str(), 0777) != 0) { if (errno != EEXIST) { - cerr << filename << ": while trying to create directory " - << path_so_far << ": " << strerror(errno) << endl; + std::cerr << filename << ": while trying to create directory " + << path_so_far << ": " << strerror(errno) << std::endl; return false; } } @@ -201,9 +200,9 @@ class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector, if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS && tree_ != NULL && tree_->VirtualFileToDiskFile(filename, &dfile)) { - cerr << dfile; + std::cerr << dfile; } else { - cerr << filename; + std::cerr << filename; } // Users typically expect 1-based line/column numbers, so we add 1 @@ -212,15 +211,16 @@ class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector, // Allow for both GCC- and Visual-Studio-compatible output. switch (format_) { case CommandLineInterface::ERROR_FORMAT_GCC: - cerr << ":" << (line + 1) << ":" << (column + 1); + std::cerr << ":" << (line + 1) << ":" << (column + 1); break; case CommandLineInterface::ERROR_FORMAT_MSVS: - cerr << "(" << (line + 1) << ") : error in column=" << (column + 1); + std::cerr << "(" << (line + 1) + << ") : error in column=" << (column + 1); break; } } - cerr << ": " << message << endl; + std::cerr << ": " << message << std::endl; } // implements io::ErrorCollector ----------------------------------- @@ -254,6 +254,9 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { // format, unless one has already been written. void AddJarManifest(); + // Get name of all output files. + void GetOutputFilenames(vector<string>* output_filenames); + // implements GeneratorContext -------------------------------------- io::ZeroCopyOutputStream* Open(const string& filename); io::ZeroCopyOutputStream* OpenForAppend(const string& filename); @@ -345,7 +348,7 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk( if (file_descriptor < 0) { int error = errno; - cerr << filename << ": " << strerror(error); + std::cerr << filename << ": " << strerror(error); return false; } @@ -369,9 +372,9 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk( if (write_result < 0) { int error = errno; - cerr << filename << ": write: " << strerror(error); + std::cerr << filename << ": write: " << strerror(error); } else { - cerr << filename << ": write() returned zero?" << endl; + std::cerr << filename << ": write() returned zero?" << std::endl; } return false; } @@ -382,7 +385,7 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk( if (close(file_descriptor) != 0) { int error = errno; - cerr << filename << ": close: " << strerror(error); + std::cerr << filename << ": close: " << strerror(error); return false; } } @@ -405,7 +408,7 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip( if (file_descriptor < 0) { int error = errno; - cerr << filename << ": " << strerror(error); + std::cerr << filename << ": " << strerror(error); return false; } @@ -421,11 +424,11 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip( zip_writer.WriteDirectory(); if (stream.GetErrno() != 0) { - cerr << filename << ": " << strerror(stream.GetErrno()) << endl; + std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl; } if (!stream.Close()) { - cerr << filename << ": " << strerror(stream.GetErrno()) << endl; + std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl; } return true; @@ -441,6 +444,14 @@ void CommandLineInterface::GeneratorContextImpl::AddJarManifest() { } } +void CommandLineInterface::GeneratorContextImpl::GetOutputFilenames( + vector<string>* output_filenames) { + for (map<string, string*>::iterator iter = files_.begin(); + iter != files_.end(); ++iter) { + output_filenames->push_back(iter->first); + } +} + io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::Open( const string& filename) { return new MemoryOutputStream(this, filename, false); @@ -490,7 +501,8 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { if (append_mode_) { (*map_slot)->append(data_); } else { - cerr << filename_ << ": Tried to write the same file twice." << endl; + std::cerr << filename_ << ": Tried to write the same file twice." + << std::endl; directory_->had_error_ = true; } return; @@ -508,8 +520,9 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { // Find the file we are going to insert into. if (*map_slot == NULL) { - cerr << filename_ << ": Tried to insert into file that doesn't exist." - << endl; + std::cerr << filename_ + << ": Tried to insert into file that doesn't exist." + << std::endl; directory_->had_error_ = true; return; } @@ -521,8 +534,8 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { string::size_type pos = target->find(magic_string); if (pos == string::npos) { - cerr << filename_ << ": insertion point \"" << insertion_point_ - << "\" not found." << endl; + std::cerr << filename_ << ": insertion point \"" << insertion_point_ + << "\" not found." << std::endl; directory_->had_error_ = true; return; } @@ -670,7 +683,6 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { // We construct a separate GeneratorContext for each output location. Note // that two code generators may output to the same location, in which case // they should share a single GeneratorContext so that OpenForInsert() works. - typedef hash_map<string, GeneratorContextImpl*> GeneratorContextMap; GeneratorContextMap output_directories; // Generate output. @@ -717,6 +729,13 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } } + if (!dependency_out_name_.empty()) { + if (!GenerateDependencyManifestFile(parsed_files, output_directories, + &source_tree)) { + return 1; + } + } + STLDeleteValues(&output_directories); if (!descriptor_set_name_.empty()) { @@ -775,6 +794,7 @@ void CommandLineInterface::Clear() { output_directives_.clear(); codec_type_.clear(); descriptor_set_name_.clear(); + dependency_out_name_.clear(); mode_ = MODE_COMPILE; print_mode_ = PRINT_NONE; @@ -793,27 +813,31 @@ bool CommandLineInterface::MakeInputsBeProtoPathRelative( input_files_[i] = virtual_file; break; case DiskSourceTree::SHADOWED: - cerr << input_files_[i] << ": Input is shadowed in the --proto_path " - "by \"" << shadowing_disk_file << "\". Either use the latter " - "file as your input or reorder the --proto_path so that the " - "former file's location comes first." << endl; + std::cerr << input_files_[i] + << ": Input is shadowed in the --proto_path by \"" + << shadowing_disk_file + << "\". Either use the latter file as your input or reorder " + "the --proto_path so that the former file's location " + "comes first." << std::endl; return false; case DiskSourceTree::CANNOT_OPEN: - cerr << input_files_[i] << ": " << strerror(errno) << endl; + std::cerr << input_files_[i] << ": " << strerror(errno) << std::endl; return false; case DiskSourceTree::NO_MAPPING: // First check if the file exists at all. if (access(input_files_[i].c_str(), F_OK) < 0) { // File does not even exist. - cerr << input_files_[i] << ": " << strerror(ENOENT) << endl; + std::cerr << input_files_[i] << ": " << strerror(ENOENT) << std::endl; } else { - cerr << input_files_[i] << ": File does not reside within any path " - "specified using --proto_path (or -I). You must specify a " - "--proto_path which encompasses this file. Note that the " - "proto_path must be an exact prefix of the .proto file " - "names -- protoc is too dumb to figure out when two paths " - "(e.g. absolute and relative) are equivalent (it's harder " - "than you think)." << endl; + std::cerr + << input_files_[i] + << ": File does not reside within any path " + "specified using --proto_path (or -I). You must specify a " + "--proto_path which encompasses this file. Note that the " + "proto_path must be an exact prefix of the .proto file " + "names -- protoc is too dumb to figure out when two paths " + "(e.g. absolute and relative) are equivalent (it's harder " + "than you think)." << std::endl; } return false; } @@ -833,9 +857,10 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { if (ParseArgument(argv[i], &name, &value)) { // Returned true => Use the next argument as the flag value. if (i + 1 == argc || argv[i+1][0] == '-') { - cerr << "Missing value for flag: " << name << endl; + std::cerr << "Missing value for flag: " << name << std::endl; if (name == "--decode") { - cerr << "To decode an unknown message, use --decode_raw." << endl; + std::cerr << "To decode an unknown message, use --decode_raw." + << std::endl; } return PARSE_ARGUMENT_FAIL; } else { @@ -860,24 +885,34 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { // Check some errror cases. bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty(); if (decoding_raw && !input_files_.empty()) { - cerr << "When using --decode_raw, no input files should be given." << endl; + std::cerr << "When using --decode_raw, no input files should be given." + << std::endl; return PARSE_ARGUMENT_FAIL; } else if (!decoding_raw && input_files_.empty()) { - cerr << "Missing input file." << endl; + std::cerr << "Missing input file." << std::endl; return PARSE_ARGUMENT_FAIL; } if (mode_ == MODE_COMPILE && output_directives_.empty() && descriptor_set_name_.empty()) { - cerr << "Missing output directives." << endl; + std::cerr << "Missing output directives." << std::endl; + return PARSE_ARGUMENT_FAIL; + } + if (mode_ != MODE_COMPILE && !dependency_out_name_.empty()) { + cerr << "Can only use --dependency_out=FILE when generating code." << endl; + return PARSE_ARGUMENT_FAIL; + } + if (!dependency_out_name_.empty() && input_files_.size() > 1) { + cerr << "Can only process one input file when using --dependency_out=FILE." + << endl; return PARSE_ARGUMENT_FAIL; } if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) { - cerr << "--include_imports only makes sense when combined with " - "--descriptor_set_out." << endl; + std::cerr << "--include_imports only makes sense when combined with " + "--descriptor_set_out." << std::endl; } if (source_info_in_descriptor_set_ && descriptor_set_name_.empty()) { - cerr << "--include_source_info only makes sense when combined with " - "--descriptor_set_out." << endl; + std::cerr << "--include_source_info only makes sense when combined with " + "--descriptor_set_out." << std::endl; } return PARSE_ARGUMENT_DONE_AND_CONTINUE; @@ -950,10 +985,12 @@ CommandLineInterface::InterpretArgument(const string& name, if (name.empty()) { // Not a flag. Just a filename. if (value.empty()) { - cerr << "You seem to have passed an empty string as one of the " - "arguments to " << executable_name_ << ". This is actually " - "sort of hard to do. Congrats. Unfortunately it is not valid " - "input so the program is going to die now." << endl; + std::cerr + << "You seem to have passed an empty string as one of the " + "arguments to " << executable_name_ + << ". This is actually " + "sort of hard to do. Congrats. Unfortunately it is not valid " + "input so the program is going to die now." << std::endl; return PARSE_ARGUMENT_FAIL; } @@ -980,14 +1017,16 @@ CommandLineInterface::InterpretArgument(const string& name, } if (disk_path.empty()) { - cerr << "--proto_path passed empty directory name. (Use \".\" for " - "current directory.)" << endl; + std::cerr + << "--proto_path passed empty directory name. (Use \".\" for " + "current directory.)" << std::endl; return PARSE_ARGUMENT_FAIL; } // Make sure disk path exists, warn otherwise. if (access(disk_path.c_str(), F_OK) < 0) { - cerr << disk_path << ": warning: directory does not exist." << endl; + std::cerr << disk_path << ": warning: directory does not exist." + << std::endl; } // Don't use make_pair as the old/default standard library on Solaris @@ -998,30 +1037,42 @@ CommandLineInterface::InterpretArgument(const string& name, } else if (name == "-o" || name == "--descriptor_set_out") { if (!descriptor_set_name_.empty()) { - cerr << name << " may only be passed once." << endl; + std::cerr << name << " may only be passed once." << std::endl; return PARSE_ARGUMENT_FAIL; } if (value.empty()) { - cerr << name << " requires a non-empty value." << endl; + std::cerr << name << " requires a non-empty value." << std::endl; return PARSE_ARGUMENT_FAIL; } if (mode_ != MODE_COMPILE) { - cerr << "Cannot use --encode or --decode and generate descriptors at the " - "same time." << endl; + std::cerr + << "Cannot use --encode or --decode and generate descriptors at the " + "same time." << std::endl; return PARSE_ARGUMENT_FAIL; } descriptor_set_name_ = value; + } else if (name == "--dependency_out") { + if (!dependency_out_name_.empty()) { + cerr << name << " may only be passed once." << endl; + return PARSE_ARGUMENT_FAIL; + } + if (value.empty()) { + cerr << name << " requires a non-empty value." << endl; + return PARSE_ARGUMENT_FAIL; + } + dependency_out_name_ = value; + } else if (name == "--include_imports") { if (imports_in_descriptor_set_) { - cerr << name << " may only be passed once." << endl; + std::cerr << name << " may only be passed once." << std::endl; return PARSE_ARGUMENT_FAIL; } imports_in_descriptor_set_ = true; } else if (name == "--include_source_info") { if (source_info_in_descriptor_set_) { - cerr << name << " may only be passed once." << endl; + std::cerr << name << " may only be passed once." << std::endl; return PARSE_ARGUMENT_FAIL; } source_info_in_descriptor_set_ = true; @@ -1032,7 +1083,7 @@ CommandLineInterface::InterpretArgument(const string& name, } else if (name == "--version") { if (!version_info_.empty()) { - cout << version_info_ << endl; + std::cout << version_info_ << std::endl; } cout << "libprotoc " << protobuf::internal::VersionString(GOOGLE_PROTOBUF_VERSION) @@ -1045,25 +1096,28 @@ CommandLineInterface::InterpretArgument(const string& name, } else if (name == "--encode" || name == "--decode" || name == "--decode_raw") { if (mode_ != MODE_COMPILE) { - cerr << "Only one of --encode and --decode can be specified." << endl; + std::cerr << "Only one of --encode and --decode can be specified." + << std::endl; return PARSE_ARGUMENT_FAIL; } if (!output_directives_.empty() || !descriptor_set_name_.empty()) { - cerr << "Cannot use " << name - << " and generate code or descriptors at the same time." << endl; + std::cerr << "Cannot use " << name + << " and generate code or descriptors at the same time." + << std::endl; return PARSE_ARGUMENT_FAIL; } mode_ = (name == "--encode") ? MODE_ENCODE : MODE_DECODE; if (value.empty() && name != "--decode_raw") { - cerr << "Type name for " << name << " cannot be blank." << endl; + std::cerr << "Type name for " << name << " cannot be blank." << std::endl; if (name == "--decode") { - cerr << "To decode an unknown message, use --decode_raw." << endl; + std::cerr << "To decode an unknown message, use --decode_raw." + << std::endl; } return PARSE_ARGUMENT_FAIL; } else if (!value.empty() && name == "--decode_raw") { - cerr << "--decode_raw does not take a parameter." << endl; + std::cerr << "--decode_raw does not take a parameter." << std::endl; return PARSE_ARGUMENT_FAIL; } @@ -1075,13 +1129,13 @@ CommandLineInterface::InterpretArgument(const string& name, } else if (value == "msvs") { error_format_ = ERROR_FORMAT_MSVS; } else { - cerr << "Unknown error format: " << value << endl; + std::cerr << "Unknown error format: " << value << std::endl; return PARSE_ARGUMENT_FAIL; } } else if (name == "--plugin") { if (plugin_prefix_.empty()) { - cerr << "This compiler does not support plugins." << endl; + std::cerr << "This compiler does not support plugins." << std::endl; return PARSE_ARGUMENT_FAIL; } @@ -1107,13 +1161,15 @@ CommandLineInterface::InterpretArgument(const string& name, } else if (name == "--print_free_field_numbers") { if (mode_ != MODE_COMPILE) { - cerr << "Cannot use " << name << " and use --encode, --decode or print " - << "other info at the same time." << endl; + std::cerr << "Cannot use " << name + << " and use --encode, --decode or print " + << "other info at the same time." << std::endl; return PARSE_ARGUMENT_FAIL; } if (!output_directives_.empty() || !descriptor_set_name_.empty()) { - cerr << "Cannot use " << name - << " and generate code or descriptors at the same time." << endl; + std::cerr << "Cannot use " << name + << " and generate code or descriptors at the same time." + << std::endl; return PARSE_ARGUMENT_FAIL; } mode_ = MODE_PRINT; @@ -1127,7 +1183,7 @@ CommandLineInterface::InterpretArgument(const string& name, // Check if it's a generator option flag. generator_info = FindOrNull(generators_by_option_name_, name); if (generator_info == NULL) { - cerr << "Unknown flag: " << name << endl; + std::cerr << "Unknown flag: " << name << std::endl; return PARSE_ARGUMENT_FAIL; } else { string* parameters = &generator_parameters_[generator_info->flag_name]; @@ -1139,8 +1195,8 @@ CommandLineInterface::InterpretArgument(const string& name, } else { // It's an output flag. Add it to the output directives. if (mode_ != MODE_COMPILE) { - cerr << "Cannot use --encode, --decode or print .proto info and " - "generate code at the same time." << endl; + std::cerr << "Cannot use --encode, --decode or print .proto info and " + "generate code at the same time." << std::endl; return PARSE_ARGUMENT_FAIL; } @@ -1172,7 +1228,7 @@ CommandLineInterface::InterpretArgument(const string& name, void CommandLineInterface::PrintHelpText() { // Sorry for indentation here; line wrapping would be uglier. - cerr << + std::cerr << "Usage: " << executable_name_ << " [OPTION] PROTO_FILES\n" "Parse PROTO_FILES and generate output based on the options given:\n" " -IPATH, --proto_path=PATH Specify the directory in which to search for\n" @@ -1206,6 +1262,9 @@ void CommandLineInterface::PrintHelpText() { " include information about the original\n" " location of each decl in the source file as\n" " well as surrounding comments.\n" +" --dependency_out=FILE Write a dependency output file in the format\n" +" expected by make. This writes the transitive\n" +" set of input file paths to FILE\n" " --error_format=FORMAT Set the format in which to print errors.\n" " FORMAT may be 'gcc' (the default) or 'msvs'\n" " (Microsoft Visual Studio format).\n" @@ -1213,9 +1272,9 @@ void CommandLineInterface::PrintHelpText() { " defined in the given proto files. Groups share\n" " the same field number space with the parent \n" " message. Extension ranges are counted as \n" -" occupied fields numbers." << endl; +" occupied fields numbers." << std::endl; if (!plugin_prefix_.empty()) { - cerr << + std::cerr << " --plugin=EXECUTABLE Specifies a plugin executable to use.\n" " Normally, protoc searches the PATH for\n" " plugins, but you may specify additional\n" @@ -1223,7 +1282,7 @@ void CommandLineInterface::PrintHelpText() { " Additionally, EXECUTABLE may be of the form\n" " NAME=PATH, in which case the given plugin name\n" " is mapped to the given executable even if\n" -" the executable's own name differs." << endl; +" the executable's own name differs." << std::endl; } for (GeneratorMap::iterator iter = generators_by_flag_name_.begin(); @@ -1231,9 +1290,9 @@ void CommandLineInterface::PrintHelpText() { // FIXME(kenton): If the text is long enough it will wrap, which is ugly, // but fixing this nicely (e.g. splitting on spaces) is probably more // trouble than it's worth. - cerr << " " << iter->first << "=OUT_DIR " - << string(19 - iter->first.size(), ' ') // Spaces for alignment. - << iter->second.help_text << endl; + std::cerr << " " << iter->first << "=OUT_DIR " + << string(19 - iter->first.size(), ' ') // Spaces for alignment. + << iter->second.help_text << std::endl; } } @@ -1256,7 +1315,7 @@ bool CommandLineInterface::GenerateOutput( if (!GeneratePluginOutput(parsed_files, plugin_name, output_directive.parameter, generator_context, &error)) { - cerr << output_directive.name << ": " << error << endl; + std::cerr << output_directive.name << ": " << error << std::endl; return false; } } else { @@ -1272,8 +1331,8 @@ bool CommandLineInterface::GenerateOutput( if (!output_directive.generator->Generate(parsed_files[i], parameters, generator_context, &error)) { // Generator returned an error. - cerr << output_directive.name << ": " << parsed_files[i]->name() << ": " - << error << endl; + std::cerr << output_directive.name << ": " << parsed_files[i]->name() + << ": " << error << std::endl; return false; } } @@ -1282,6 +1341,76 @@ bool CommandLineInterface::GenerateOutput( return true; } +bool CommandLineInterface::GenerateDependencyManifestFile( + const vector<const FileDescriptor*>& parsed_files, + const GeneratorContextMap& output_directories, + DiskSourceTree* source_tree) { + FileDescriptorSet file_set; + + set<const FileDescriptor*> already_seen; + for (int i = 0; i < parsed_files.size(); i++) { + GetTransitiveDependencies(parsed_files[i], + false, + &already_seen, + file_set.mutable_file()); + } + + vector<string> output_filenames; + for (GeneratorContextMap::const_iterator iter = output_directories.begin(); + iter != output_directories.end(); ++iter) { + const string& location = iter->first; + GeneratorContextImpl* directory = iter->second; + vector<string> relative_output_filenames; + directory->GetOutputFilenames(&relative_output_filenames); + for (int i = 0; i < relative_output_filenames.size(); i++) { + string output_filename = location + relative_output_filenames[i]; + if (output_filename.compare(0, 2, "./") == 0) { + output_filename = output_filename.substr(2); + } + output_filenames.push_back(output_filename); + } + } + + int fd; + do { + fd = open(dependency_out_name_.c_str(), + O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); + } while (fd < 0 && errno == EINTR); + + if (fd < 0) { + perror(dependency_out_name_.c_str()); + return false; + } + + io::FileOutputStream out(fd); + io::Printer printer(&out, '$'); + + for (int i = 0; i < output_filenames.size(); i++) { + printer.Print(output_filenames[i].c_str()); + if (i == output_filenames.size() - 1) { + printer.Print(":"); + } else { + printer.Print(" \\\n"); + } + } + + for (int i = 0; i < file_set.file_size(); i++) { + const FileDescriptorProto& file = file_set.file(i); + const string& virtual_file = file.name(); + string disk_file; + if (source_tree && + source_tree->VirtualFileToDiskFile(virtual_file, &disk_file)) { + printer.Print(" $disk_file$", "disk_file", disk_file); + if (i < file_set.file_size() - 1) printer.Print("\\\n"); + } else { + cerr << "Unable to identify path for file " << virtual_file << endl; + return false; + } + } + + return true; +} + bool CommandLineInterface::GeneratePluginOutput( const vector<const FileDescriptor*>& parsed_files, const string& plugin_name, @@ -1365,7 +1494,7 @@ bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) { // Look up the type. const Descriptor* type = pool->FindMessageTypeByName(codec_type_); if (type == NULL) { - cerr << "Type not defined: " << codec_type_ << endl; + std::cerr << "Type not defined: " << codec_type_ << std::endl; return false; } @@ -1391,32 +1520,32 @@ bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) { parser.AllowPartialMessage(true); if (!parser.Parse(&in, message.get())) { - cerr << "Failed to parse input." << endl; + std::cerr << "Failed to parse input." << std::endl; return false; } } else { // Input is binary. if (!message->ParsePartialFromZeroCopyStream(&in)) { - cerr << "Failed to parse input." << endl; + std::cerr << "Failed to parse input." << std::endl; return false; } } if (!message->IsInitialized()) { - cerr << "warning: Input message is missing required fields: " - << message->InitializationErrorString() << endl; + std::cerr << "warning: Input message is missing required fields: " + << message->InitializationErrorString() << std::endl; } if (mode_ == MODE_ENCODE) { // Output is binary. if (!message->SerializePartialToZeroCopyStream(&out)) { - cerr << "output: I/O error." << endl; + std::cerr << "output: I/O error." << std::endl; return false; } } else { // Output is text. if (!TextFormat::Print(*message, &out)) { - cerr << "output: I/O error." << endl; + std::cerr << "output: I/O error." << std::endl; return false; } } @@ -1458,12 +1587,14 @@ bool CommandLineInterface::WriteDescriptorSet( io::FileOutputStream out(fd); if (!file_set.SerializeToZeroCopyStream(&out)) { - cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) << endl; + std::cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) + << std::endl; out.Close(); return false; } if (!out.Close()) { - cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) << endl; + std::cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) + << std::endl; return false; } @@ -1582,7 +1713,7 @@ void FormatFreeFieldNumbers(const string& name, if (next_free_number <= FieldDescriptor::kMaxNumber) { StringAppendF(&output, " %d-INF", next_free_number); } - cout << output << endl; + std::cout << output << std::endl; } } // namespace diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index 74a0adb4..7e611c44 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -39,6 +39,7 @@ #define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__ #include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/hash.h> #include <string> #include <vector> #include <map> @@ -190,6 +191,7 @@ class LIBPROTOC_EXPORT CommandLineInterface { class ErrorPrinter; class GeneratorContextImpl; class MemoryOutputStream; + typedef hash_map<string, GeneratorContextImpl*> GeneratorContextMap; // Clear state from previous Run(). void Clear(); @@ -247,6 +249,12 @@ class LIBPROTOC_EXPORT CommandLineInterface { // Implements the --descriptor_set_out option. bool WriteDescriptorSet(const vector<const FileDescriptor*> parsed_files); + // Implements the --dependency_out option + bool GenerateDependencyManifestFile( + const vector<const FileDescriptor*>& parsed_files, + const GeneratorContextMap& output_directories, + DiskSourceTree* source_tree); + // Get all transitive dependencies of the given file (including the file // itself), adding them to the given list of FileDescriptorProtos. The // protos will be ordered such that every file is listed before any file that @@ -353,6 +361,10 @@ class LIBPROTOC_EXPORT CommandLineInterface { // FileDescriptorSet should be written. Otherwise, empty. string descriptor_set_name_; + // If --dependency_out was given, this is the path to the file where the + // dependency file will be written. Otherwise, empty. + string dependency_out_name_; + // True if --include_imports was given, meaning that we should // write all transitive dependencies to the DescriptorSet. Otherwise, only // the .proto files listed on the command-line are added. diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index f4606c8d..a2cbbdc6 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -64,6 +64,9 @@ #include <gtest/gtest.h> +// Disable the whole test when we use tcmalloc for "draconian" heap checks, in +// which case tcmalloc will print warnings that fail the plugin tests. +#if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN namespace google { namespace protobuf { namespace compiler { @@ -112,6 +115,11 @@ class CommandLineInterfaceTest : public testing::Test { // Create a subdirectory within temp_directory_. void CreateTempDir(const string& name); + // Change working directory to temp directory. + void SwitchToTempDirectory() { + File::ChangeWorkingDirectory(temp_directory_); + } + void SetInputsAreProtoPathRelative(bool enable) { cli_.SetInputsAreProtoPathRelative(enable); } @@ -176,6 +184,9 @@ class CommandLineInterfaceTest : public testing::Test { void ReadDescriptorSet(const string& filename, FileDescriptorSet* descriptor_set); + void ExpectFileContent(const string& filename, + const string& content); + private: // The object we are testing. CommandLineInterface cli_; @@ -456,6 +467,17 @@ void CommandLineInterfaceTest::ExpectCapturedStdout( EXPECT_EQ(expected_text, captured_stdout_); } + +void CommandLineInterfaceTest::ExpectFileContent( + const string& filename, const string& content) { + string path = temp_directory_ + "/" + filename; + string file_contents; + GOOGLE_CHECK_OK(File::GetContents(path, &file_contents, true)); + + EXPECT_EQ(StringReplace(content, "$tmpdir", temp_directory_, true), + file_contents); +} + // =================================================================== TEST_F(CommandLineInterfaceTest, BasicOutput) { @@ -725,7 +747,7 @@ TEST_F(CommandLineInterfaceTest, ColonDelimitedPath) { #endif Run("protocol_compiler --test_out=$tmpdir " - "--proto_path=$tmpdir/a"PATH_SEPARATOR"$tmpdir/b foo.proto"); + "--proto_path=$tmpdir/a" PATH_SEPARATOR "$tmpdir/b foo.proto"); #undef PATH_SEPARATOR @@ -940,6 +962,71 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) { EXPECT_TRUE(descriptor_set.file(1).has_source_code_info()); } +TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileGivenTwoInputs) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); + + Run("protocol_compiler --dependency_out=$tmpdir/manifest " + "--test_out=$tmpdir --proto_path=$tmpdir bar.proto foo.proto"); + + ExpectErrorText( + "Can only process one input file when using --dependency_out=FILE.\n"); +} + +TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); + + string current_working_directory = getcwd(NULL, 0); + SwitchToTempDirectory(); + + Run("protocol_compiler --dependency_out=manifest --test_out=. " + "bar.proto"); + + ExpectNoErrors(); + + ExpectFileContent("manifest", + "bar.proto.MockCodeGenerator.test_generator: " + "foo.proto\\\n bar.proto"); + + File::ChangeWorkingDirectory(current_working_directory); +} + +TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForAbsolutePath) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); + + Run("protocol_compiler --dependency_out=$tmpdir/manifest " + "--test_out=$tmpdir --proto_path=$tmpdir bar.proto"); + + ExpectNoErrors(); + + ExpectFileContent("manifest", + "$tmpdir/bar.proto.MockCodeGenerator.test_generator: " + "$tmpdir/foo.proto\\\n $tmpdir/bar.proto"); +} + // ------------------------------------------------------------------- TEST_F(CommandLineInterfaceTest, ParseErrors) { @@ -1662,4 +1749,6 @@ TEST_F(EncodeDecodeTest, ProtoParseError) { } // namespace compiler } // namespace protobuf + +#endif // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN } // namespace google diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc index 48788197..13ed0b64 100644 --- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc @@ -98,7 +98,8 @@ class MockGeneratorContext : public GeneratorContext { &actual_contents, true)); EXPECT_TRUE(actual_contents == *expected_contents) << physical_filename << " needs to be regenerated. Please run " - "generate_descriptor_proto.sh and add this file " + "google/protobuf/compiler/release_compiler.sh and " + "generate_descriptor_proto.sh. Then add this file " "to your CL."; } diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc index 3ce1f120..3eb20ab1 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc @@ -47,7 +47,7 @@ namespace cpp { namespace { // The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value -// is kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the +// is ::google::protobuf::kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the // generation of the GOOGLE_ARRAYSIZE constant. bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) { int32 max_value = descriptor->value(0)->number(); @@ -56,7 +56,7 @@ bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) { max_value = descriptor->value(i)->number(); } } - return max_value != kint32max; + return max_value != ::google::protobuf::kint32max; } } // namespace @@ -82,7 +82,7 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { const EnumValueDescriptor* max_value = descriptor_->value(0); for (int i = 0; i < descriptor_->value_count(); i++) { - vars["name"] = descriptor_->value(i)->name(); + vars["name"] = EnumValueName(descriptor_->value(i)); // In C++, an value of -2147483648 gets interpreted as the negative of // 2147483648, and since 2147483648 can't fit in an integer, this produces a // compiler warning. This works around that issue. @@ -90,6 +90,7 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { vars["prefix"] = (descriptor_->containing_type() == NULL) ? "" : classname_ + "_"; + if (i > 0) printer->Print(",\n"); printer->Print(vars, "$prefix$$name$ = $number$"); @@ -113,8 +114,8 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { printer->Outdent(); printer->Print("\n};\n"); - vars["min_name"] = min_value->name(); - vars["max_name"] = max_value->name(); + vars["min_name"] = EnumValueName(min_value); + vars["max_name"] = EnumValueName(max_value); if (options_.dllexport_decl.empty()) { vars["dllexport"] = ""; @@ -153,9 +154,12 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { void EnumGenerator:: GenerateGetEnumDescriptorSpecializations(io::Printer* printer) { + printer->Print( + "template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type " + "{};\n", + "classname", ClassName(descriptor_, true)); if (HasDescriptorMethods(descriptor_->file())) { printer->Print( - "template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type {};\n" "template <>\n" "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n" " return $classname$_descriptor();\n" @@ -171,7 +175,7 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) { printer->Print(vars, "typedef $classname$ $nested_name$;\n"); for (int j = 0; j < descriptor_->value_count(); j++) { - vars["tag"] = descriptor_->value(j)->name(); + vars["tag"] = EnumValueName(descriptor_->value(j)); printer->Print(vars, "static const $nested_name$ $tag$ = $classname$_$tag$;\n"); } @@ -275,7 +279,7 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) { vars["parent"] = ClassName(descriptor_->containing_type(), false); vars["nested_name"] = descriptor_->name(); for (int i = 0; i < descriptor_->value_count(); i++) { - vars["value"] = descriptor_->value(i)->name(); + vars["value"] = EnumValueName(descriptor_->value(i)); printer->Print(vars, "const $classname$ $parent$::$value$;\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc index 17926135..74989703 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc @@ -76,23 +76,26 @@ GeneratePrivateMembers(io::Printer* printer) const { void EnumFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline $type$ $name$() const$deprecation$;\n" - "inline void set_$name$($type$ value)$deprecation$;\n"); + "$type$ $name$() const$deprecation$;\n" + "void set_$name$($type$ value)$deprecation$;\n"); } void EnumFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$() const {\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map<string, string> variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ $type$ $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return static_cast< $type$ >($name$_);\n" "}\n" - "inline void $classname$::set_$name$($type$ value) {\n"); + "$inline$ void $classname$::set_$name$($type$ value) {\n"); if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, + printer->Print(variables, " assert($type$_IsValid(value));\n"); } - printer->Print(variables_, + printer->Print(variables, " $set_hasbit$\n" " $name$_ = value;\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" @@ -181,21 +184,24 @@ EnumOneofFieldGenerator(const FieldDescriptor* descriptor, EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {} void EnumOneofFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$() const {\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map<string, string> variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ $type$ $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " if (has_$name$()) {\n" " return static_cast< $type$ >($oneof_prefix$$name$_);\n" " }\n" " return static_cast< $type$ >($default$);\n" "}\n" - "inline void $classname$::set_$name$($type$ value) {\n"); + "$inline$ void $classname$::set_$name$($type$ value) {\n"); if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, + printer->Print(variables, " assert($type$_IsValid(value));\n"); } - printer->Print(variables_, + printer->Print(variables, " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" @@ -246,46 +252,49 @@ GeneratePrivateMembers(io::Printer* printer) const { void RepeatedEnumFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline $type$ $name$(int index) const$deprecation$;\n" - "inline void set_$name$(int index, $type$ value)$deprecation$;\n" - "inline void add_$name$($type$ value)$deprecation$;\n"); + "$type$ $name$(int index) const$deprecation$;\n" + "void set_$name$(int index, $type$ value)$deprecation$;\n" + "void add_$name$($type$ value)$deprecation$;\n"); printer->Print(variables_, - "inline const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n" - "inline ::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n"); + "const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n" + "::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n"); } void RepeatedEnumFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$(int index) const {\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map<string, string> variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ $type$ $classname$::$name$(int index) const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return static_cast< $type$ >($name$_.Get(index));\n" "}\n" - "inline void $classname$::set_$name$(int index, $type$ value) {\n"); + "$inline$ void $classname$::set_$name$(int index, $type$ value) {\n"); if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, + printer->Print(variables, " assert($type$_IsValid(value));\n"); } - printer->Print(variables_, + printer->Print(variables, " $name$_.Set(index, value);\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" - "inline void $classname$::add_$name$($type$ value) {\n"); + "$inline$ void $classname$::add_$name$($type$ value) {\n"); if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, + printer->Print(variables, " assert($type$_IsValid(value));\n"); } - printer->Print(variables_, + printer->Print(variables, " $name$_.Add(value);\n" " // @@protoc_insertion_point(field_add:$full_name$)\n" "}\n"); - printer->Print(variables_, - "inline const ::google::protobuf::RepeatedField<int>&\n" + printer->Print(variables, + "$inline$ const ::google::protobuf::RepeatedField<int>&\n" "$classname$::$name$() const {\n" " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" - "inline ::google::protobuf::RepeatedField<int>*\n" + "$inline$ ::google::protobuf::RepeatedField<int>*\n" "$classname$::mutable_$name$() {\n" " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" @@ -344,20 +353,34 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { void RepeatedEnumFieldGenerator:: GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { if (!descriptor_->options().packed()) { - // We use a non-inlined implementation in this case, since this path will - // rarely be executed. - printer->Print(variables_, - "DO_((::google::protobuf::internal::WireFormatLite::ReadPackedEnumNoInline(\n" - " input,\n"); + // This path is rarely executed, so we use a non-inlined implementation. if (HasPreservingUnknownEnumSemantics(descriptor_->file())) { printer->Print(variables_, - " NULL,\n"); + "DO_((::google::protobuf::internal::" + "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n" + " input,\n" + " $number$,\n" + " NULL,\n" + " NULL,\n" + " this->mutable_$name$())));\n"); + } else if (UseUnknownFieldSet(descriptor_->file())) { + printer->Print(variables_, + "DO_((::google::protobuf::internal::WireFormat::ReadPackedEnumPreserveUnknowns(\n" + " input,\n" + " $number$,\n" + " $type$_IsValid,\n" + " mutable_unknown_fields(),\n" + " this->mutable_$name$())));\n"); } else { printer->Print(variables_, - " &$type$_IsValid,\n"); + "DO_((::google::protobuf::internal::" + "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n" + " input,\n" + " $number$,\n" + " $type$_IsValid,\n" + " &unknown_fields_stream,\n" + " this->mutable_$name$())));\n"); } - printer->Print(variables_, - " this->mutable_$name$())));\n"); } else { printer->Print(variables_, "::google::protobuf::uint32 length;\n" @@ -376,6 +399,16 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { printer->Print(variables_, " if ($type$_IsValid(value)) {\n" " add_$name$(static_cast< $type$ >(value));\n" + " } else {\n"); + if (UseUnknownFieldSet(descriptor_->file())) { + printer->Print(variables_, + " mutable_unknown_fields()->AddVarint($number$, value);\n"); + } else { + printer->Print(variables_, + " unknown_fields_stream.WriteVarint32(tag);\n" + " unknown_fields_stream.WriteVarint32(value);\n"); + } + printer->Print( " }\n"); } printer->Print(variables_, diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h index def2b232..5b1d01ea 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h @@ -53,7 +53,8 @@ class EnumFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; @@ -78,7 +79,8 @@ class EnumOneofFieldGenerator : public EnumFieldGenerator { ~EnumOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; @@ -96,7 +98,8 @@ class RepeatedEnumFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.h b/src/google/protobuf/compiler/cpp/cpp_extension.h index d354c16a..1c1caf1f 100644 --- a/src/google/protobuf/compiler/cpp/cpp_extension.h +++ b/src/google/protobuf/compiler/cpp/cpp_extension.h @@ -57,7 +57,7 @@ namespace cpp { class ExtensionGenerator { public: // See generator.cc for the meaning of dllexport_decl. - explicit ExtensionGenerator(const FieldDescriptor* desycriptor, + explicit ExtensionGenerator(const FieldDescriptor* descriptor, const Options& options); ~ExtensionGenerator(); diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h index c37fe0be..cd2b6b75 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_field.h @@ -89,7 +89,7 @@ class FieldGenerator { // Generate inline definitions of accessor functions for this field. // These are placed inside the header after all class definitions. virtual void GenerateInlineAccessorDefinitions( - io::Printer* printer) const = 0; + io::Printer* printer, bool is_inline) const = 0; // Generate definitions of accessors that aren't inlined. These are // placed somewhere in the .cc file. diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index fae4df40..a98c7d92 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -136,8 +136,11 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { printer->Print( "#include <google/protobuf/arena.h>\n" "#include <google/protobuf/arenastring.h>\n" - "#include <google/protobuf/generated_message_util.h>\n" - "#include <google/protobuf/metadata.h>\n"); + "#include <google/protobuf/generated_message_util.h>\n"); + if (UseUnknownFieldSet(file_)) { + printer->Print( + "#include <google/protobuf/metadata.h>\n"); + } if (file_->message_type_count() > 0) { if (HasDescriptorMethods(file_)) { printer->Print( @@ -152,13 +155,24 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { "#include <google/protobuf/extension_set.h>\n"); if (HasMapFields(file_)) { printer->Print( - "#include <google/protobuf/map.h>\n" - "#include <google/protobuf/map_field_inl.h>\n"); + "#include <google/protobuf/map.h>\n"); + if (HasDescriptorMethods(file_)) { + printer->Print( + "#include <google/protobuf/map_field_inl.h>\n"); + } else { + printer->Print( + "#include <google/protobuf/map_field_lite.h>\n"); + } } - if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) { - printer->Print( - "#include <google/protobuf/generated_enum_reflection.h>\n"); + if (HasEnumDefinitions(file_)) { + if (HasDescriptorMethods(file_)) { + printer->Print( + "#include <google/protobuf/generated_enum_reflection.h>\n"); + } else { + printer->Print( + "#include <google/protobuf/generated_enum_util.h>\n"); + } } if (HasGenericServices(file_)) { @@ -272,15 +286,17 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { printer->Print(kThickSeparator); printer->Print("\n"); - + printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n"); // Generate class inline methods. for (int i = 0; i < file_->message_type_count(); i++) { if (i > 0) { printer->Print(kThinSeparator); printer->Print("\n"); } - message_generators_[i]->GenerateInlineMethods(printer); + message_generators_[i]->GenerateInlineMethods(printer, + /* is_inline = */ true); } + printer->Print("#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS\n"); printer->Print( "\n" @@ -290,7 +306,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { GenerateNamespaceClosers(printer); // Emit GetEnumDescriptor specializations into google::protobuf namespace: - if (HasDescriptorMethods(file_)) { + if (HasEnumDefinitions(file_)) { // The SWIG conditional is to avoid a null-pointer dereference // (bug 1984964) in swig-1.3.21 resulting from the following syntax: // namespace X { void Y<Z::W>(); } @@ -417,6 +433,12 @@ void FileGenerator::GenerateSource(io::Printer* printer) { printer->Print(kThickSeparator); printer->Print("\n"); message_generators_[i]->GenerateClassMethods(printer); + + printer->Print("#if PROTOBUF_INLINE_NOT_IN_HEADERS\n"); + // Generate class inline methods. + message_generators_[i]->GenerateInlineMethods(printer, + /* is_inline = */ false); + printer->Print("#endif // PROTOBUF_INLINE_NOT_IN_HEADERS\n"); } if (HasGenericServices(file_)) { diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc index 28c4dd54..4e7155c3 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -176,6 +176,14 @@ string FieldName(const FieldDescriptor* field) { return result; } +string EnumValueName(const EnumValueDescriptor* enum_value) { + string result = enum_value->name(); + if (kKeywords.count(result) > 0) { + result.append("_"); + } + return result; +} + string FieldConstantName(const FieldDescriptor *field) { string field_name = UnderscoresToCamelCase(field->name(), true); string result = "k" + field_name + "FieldNumber"; @@ -352,9 +360,7 @@ string FilenameIdentifier(const string& filename) { } else { // Not alphanumeric. To avoid any possibility of name conflicts we // use the hex code for the character. - result.push_back('_'); - char buffer[kFastToBufferSize]; - result.append(FastHexToBuffer(static_cast<uint8>(filename[i]), buffer)); + StrAppend(&result, "_", ToHex(static_cast<uint8>(filename[i]))); } } return result; @@ -508,6 +514,13 @@ bool IsStringOrMessage(const FieldDescriptor* field) { return false; } +FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field) { + GOOGLE_DCHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_STRING); + // Open-source protobuf release only supports STRING ctype. + return FieldOptions::STRING; + +} + } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h index e60fa7c2..284fa2c1 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -74,6 +74,9 @@ string SuperClassName(const Descriptor* descriptor); // anyway, so normally this just returns field->name(). string FieldName(const FieldDescriptor* field); +// Get the sanitized name that should be used for the given enum in C++ code. +string EnumValueName(const EnumValueDescriptor* enum_value); + // Get the unqualified name that should be used for a field's field // number constant. string FieldConstantName(const FieldDescriptor *field); @@ -211,6 +214,10 @@ inline bool IsMapEntryMessage(const Descriptor* descriptor) { // Returns true if the field's CPPTYPE is string or message. bool IsStringOrMessage(const FieldDescriptor* field); +// For a string field, returns the effective ctype. If the actual ctype is +// not supported, returns the default of STRING. +FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field); + string UnderscoresToCamelCase(const string& input, bool cap_next_letter); inline bool HasFieldPresence(const FileDescriptor* file) { diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc index 0154eeb8..8c38db2b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc @@ -31,6 +31,7 @@ #include <google/protobuf/compiler/cpp/cpp_map_field.h> #include <google/protobuf/compiler/cpp/cpp_helpers.h> #include <google/protobuf/io/printer.h> +#include <google/protobuf/wire_format.h> #include <google/protobuf/stubs/strutil.h> namespace google { @@ -72,14 +73,21 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["val_cpp"] = PrimitiveTypeName(val->cpp_type()); (*variables)["wrapper"] = "EntryWrapper"; } - (*variables)["key_type"] = - "::google::protobuf::FieldDescriptor::TYPE_" + + (*variables)["key_wire_type"] = + "::google::protobuf::internal::WireFormatLite::TYPE_" + ToUpper(DeclaredTypeMethodName(key->type())); - (*variables)["val_type"] = - "::google::protobuf::FieldDescriptor::TYPE_" + + (*variables)["val_wire_type"] = + "::google::protobuf::internal::WireFormatLite::TYPE_" + ToUpper(DeclaredTypeMethodName(val->type())); (*variables)["map_classname"] = ClassName(descriptor->message_type(), false); - (*variables)["number"] = Int32ToString(descriptor->number()); + (*variables)["number"] = SimpleItoa(descriptor->number()); + (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); + + if (HasDescriptorMethods(descriptor->file())) { + (*variables)["lite"] = ""; + } else { + (*variables)["lite"] = "Lite"; + } if (!IsProto3Field(descriptor) && val->type() == FieldDescriptor::TYPE_ENUM) { @@ -102,33 +110,40 @@ MapFieldGenerator::~MapFieldGenerator() {} void MapFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { printer->Print(variables_, - "typedef ::google::protobuf::internal::MapEntry<\n" + "typedef ::google::protobuf::internal::MapEntryLite<\n" " $key_cpp$, $val_cpp$,\n" - " $key_type$,\n" - " $val_type$, $default_enum_value$>\n" + " $key_wire_type$,\n" + " $val_wire_type$,\n" + " $default_enum_value$ >\n" " $map_classname$;\n" - "::google::protobuf::internal::MapField< $key_cpp$, $val_cpp$," - "$key_type$, $val_type$, $default_enum_value$ > $name$_;\n"); + "::google::protobuf::internal::MapField$lite$<\n" + " $key_cpp$, $val_cpp$,\n" + " $key_wire_type$,\n" + " $val_wire_type$,\n" + " $default_enum_value$ > $name$_;\n"); } void MapFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n" + "const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n" " $name$() const$deprecation$;\n" - "inline ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n" + "::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n" " mutable_$name$()$deprecation$;\n"); } void MapFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map<string, string> variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n" "$classname$::$name$() const {\n" " // @@protoc_insertion_point(field_map:$full_name$)\n" " return $name$_.GetMap();\n" "}\n" - "inline ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n" + "$inline$ ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n" "$classname$::mutable_$name$() {\n" " // @@protoc_insertion_point(field_mutable_map:$full_name$)\n" " return $name$_.MutableMap();\n" @@ -198,11 +213,29 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { " if ($val_cpp$_IsValid(*entry->mutable_value())) {\n" " (*mutable_$name$())[entry->key()] =\n" " static_cast<$val_cpp$>(*entry->mutable_value());\n" - " } else {\n" - " mutable_unknown_fields()->AddLengthDelimited($number$, data);\n" + " } else {\n"); + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print(variables_, + " mutable_unknown_fields()" + "->AddLengthDelimited($number$, data);\n"); + } else { + printer->Print(variables_, + " unknown_fields_stream.WriteVarint32($tag$);\n" + " unknown_fields_stream.WriteVarint32(data.size());\n" + " unknown_fields_stream.WriteString(data);\n"); + } + + + printer->Print(variables_, " }\n" "}\n"); } + + // If entry is allocated by arena, its desctructor should be avoided. + if (SupportsArenas(descriptor_)) { + printer->Print(variables_, + "if (entry->GetArena() != NULL) entry.release();\n"); + } } void MapFieldGenerator:: @@ -211,12 +244,31 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { "{\n" " ::google::protobuf::scoped_ptr<$map_classname$> entry;\n" " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" - " it = $name$().begin(); it != $name$().end(); ++it) {\n" + " it = $name$().begin(); it != $name$().end(); ++it) {\n"); + + // If entry is allocated by arena, its desctructor should be avoided. + if (SupportsArenas(descriptor_)) { + printer->Print(variables_, + " if (entry.get() != NULL && entry->GetArena() != NULL) {\n" + " entry.release();\n" + " }\n"); + } + + printer->Print(variables_, " entry.reset($name$_.New$wrapper$(it->first, it->second));\n" " ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n" " $number$, *entry, output);\n" - " }\n" - "}\n"); + " }\n"); + + // If entry is allocated by arena, its desctructor should be avoided. + if (SupportsArenas(descriptor_)) { + printer->Print(variables_, + " if (entry.get() != NULL && entry->GetArena() != NULL) {\n" + " entry.release();\n" + " }\n"); + } + + printer->Print("}\n"); } void MapFieldGenerator:: @@ -225,13 +277,32 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { "{\n" " ::google::protobuf::scoped_ptr<$map_classname$> entry;\n" " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" - " it = $name$().begin(); it != $name$().end(); ++it) {\n" + " it = $name$().begin(); it != $name$().end(); ++it) {\n"); + + // If entry is allocated by arena, its desctructor should be avoided. + if (SupportsArenas(descriptor_)) { + printer->Print(variables_, + " if (entry.get() != NULL && entry->GetArena() != NULL) {\n" + " entry.release();\n" + " }\n"); + } + + printer->Print(variables_, " entry.reset($name$_.New$wrapper$(it->first, it->second));\n" " target = ::google::protobuf::internal::WireFormatLite::\n" " Write$declared_type$NoVirtualToArray(\n" " $number$, *entry, target);\n" - " }\n" - "}\n"); + " }\n"); + + // If entry is allocated by arena, its desctructor should be avoided. + if (SupportsArenas(descriptor_)) { + printer->Print(variables_, + " if (entry.get() != NULL && entry->GetArena() != NULL) {\n" + " entry.release();\n" + " }\n"); + } + + printer->Print("}\n"); } void MapFieldGenerator:: @@ -241,12 +312,31 @@ GenerateByteSize(io::Printer* printer) const { "{\n" " ::google::protobuf::scoped_ptr<$map_classname$> entry;\n" " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" - " it = $name$().begin(); it != $name$().end(); ++it) {\n" + " it = $name$().begin(); it != $name$().end(); ++it) {\n"); + + // If entry is allocated by arena, its desctructor should be avoided. + if (SupportsArenas(descriptor_)) { + printer->Print(variables_, + " if (entry.get() != NULL && entry->GetArena() != NULL) {\n" + " entry.release();\n" + " }\n"); + } + + printer->Print(variables_, " entry.reset($name$_.New$wrapper$(it->first, it->second));\n" " total_size += ::google::protobuf::internal::WireFormatLite::\n" " $declared_type$SizeNoVirtual(*entry);\n" - " }\n" - "}\n"); + " }\n"); + + // If entry is allocated by arena, its desctructor should be avoided. + if (SupportsArenas(descriptor_)) { + printer->Print(variables_, + " if (entry.get() != NULL && entry->GetArena() != NULL) {\n" + " entry.release();\n" + " }\n"); + } + + printer->Print("}\n"); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.h b/src/google/protobuf/compiler/cpp/cpp_map_field.h index 0ff032fd..d27d4851 100644 --- a/src/google/protobuf/compiler/cpp/cpp_map_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_map_field.h @@ -50,7 +50,8 @@ class MapFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index b42f32b8..bafa36f5 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -87,8 +87,8 @@ const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { for (int i = 0; i < descriptor->field_count(); i++) { fields[i] = descriptor->field(i); } - sort(fields, fields + descriptor->field_count(), - FieldOrderingByNumber()); + std::sort(fields, fields + descriptor->field_count(), + FieldOrderingByNumber()); return fields; } @@ -253,7 +253,7 @@ void OptimizePadding(vector<const FieldDescriptor*>* fields) { // Sort by preferred location to keep fields as close to their original // location as possible. Using stable_sort ensures that the output is // consistent across runs. - stable_sort(aligned_to_4.begin(), aligned_to_4.end()); + std::stable_sort(aligned_to_4.begin(), aligned_to_4.end()); // Now group fields aligned to 4 bytes (or the 4-field groups created above) // into pairs, and treat those like a single field aligned to 8 bytes. @@ -269,7 +269,7 @@ void OptimizePadding(vector<const FieldDescriptor*>* fields) { aligned_to_8.push_back(field_group); } // Sort by preferred location. - stable_sort(aligned_to_8.begin(), aligned_to_8.end()); + std::stable_sort(aligned_to_8.begin(), aligned_to_8.end()); // Now pull out all the FieldDescriptors in order. fields->clear(); @@ -280,10 +280,6 @@ void OptimizePadding(vector<const FieldDescriptor*>* fields) { } } -string MessageTypeProtoName(const FieldDescriptor* field) { - return field->message_type()->full_name(); -} - // Emits an if-statement with a condition that evaluates to true if |field| is // considered non-default (will be sent over the wire), for message types // without true field presence. Should only be called if @@ -351,11 +347,11 @@ void CollectMapInfo(const Descriptor* descriptor, default: (*variables)["val"] = PrimitiveTypeName(val->cpp_type()); } - (*variables)["key_type"] = - "::google::protobuf::FieldDescriptor::TYPE_" + + (*variables)["key_wire_type"] = + "::google::protobuf::internal::WireFormatLite::TYPE_" + ToUpper(DeclaredTypeMethodName(key->type())); - (*variables)["val_type"] = - "::google::protobuf::FieldDescriptor::TYPE_" + + (*variables)["val_wire_type"] = + "::google::protobuf::internal::WireFormatLite::TYPE_" + ToUpper(DeclaredTypeMethodName(val->type())); } @@ -457,17 +453,17 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { vars["constant_name"] = FieldConstantName(field); if (field->is_repeated()) { - printer->Print(vars, "inline int $name$_size() const$deprecation$;\n"); + printer->Print(vars, "int $name$_size() const$deprecation$;\n"); } else if (HasHasMethod(field)) { - printer->Print(vars, "inline bool has_$name$() const$deprecation$;\n"); + printer->Print(vars, "bool has_$name$() const$deprecation$;\n"); } else if (HasPrivateHasMethod(field)) { printer->Print(vars, "private:\n" - "inline bool has_$name$() const$deprecation$;\n" + "bool has_$name$() const$deprecation$;\n" "public:\n"); } - printer->Print(vars, "inline void clear_$name$()$deprecation$;\n"); + printer->Print(vars, "void clear_$name$()$deprecation$;\n"); printer->Print(vars, "static const int $constant_name$ = $number$;\n"); // Generate type-specific accessor declarations. @@ -486,7 +482,7 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { printer->Print( - "inline $camel_oneof_name$Case $oneof_name$_case() const;\n", + "$camel_oneof_name$Case $oneof_name$_case() const;\n", "camel_oneof_name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true), "oneof_name", descriptor_->oneof_decl(i)->name()); @@ -494,7 +490,7 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { } void MessageGenerator:: -GenerateFieldAccessorDefinitions(io::Printer* printer) { +GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) { printer->Print("// $classname$\n\n", "classname", classname_); for (int i = 0; i < descriptor_->field_count(); i++) { @@ -504,11 +500,12 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { map<string, string> vars; SetCommonFieldVariables(field, &vars, options_); + vars["inline"] = is_inline ? "inline" : ""; // Generate has_$name$() or $name$_size(). if (field->is_repeated()) { printer->Print(vars, - "inline int $classname$::$name$_size() const {\n" + "$inline$ int $classname$::$name$_size() const {\n" " return $name$_.size();\n" "}\n"); } else if (field->containing_oneof()) { @@ -522,11 +519,11 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { vars["oneof_name"] = field->containing_oneof()->name(); vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index()); printer->Print(vars, - "inline bool $classname$::has_$name$() const {\n" + "$inline$ bool $classname$::has_$name$() const {\n" " return $oneof_name$_case() == k$field_name$;\n" "}\n"); printer->Print(vars, - "inline void $classname$::set_has_$name$() {\n" + "$inline$ void $classname$::set_has_$name$() {\n" " _oneof_case_[$oneof_index$] = k$field_name$;\n" "}\n"); } else { @@ -539,13 +536,13 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { vars["has_mask"] = FastHex32ToBuffer(1u << (field->index() % 32), buffer); printer->Print(vars, - "inline bool $classname$::has_$name$() const {\n" + "$inline$ bool $classname$::has_$name$() const {\n" " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n" "}\n" - "inline void $classname$::set_has_$name$() {\n" + "$inline$ void $classname$::set_has_$name$() {\n" " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n" "}\n" - "inline void $classname$::clear_has_$name$() {\n" + "$inline$ void $classname$::clear_has_$name$() {\n" " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n" "}\n" ); @@ -555,13 +552,13 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { bool is_lazy = false; if (is_lazy) { printer->Print(vars, - "inline bool $classname$::has_$name$() const {\n" + "$inline$ bool $classname$::has_$name$() const {\n" " return !$name$_.IsCleared();\n" "}\n"); } else { printer->Print(vars, - "inline bool $classname$::has_$name$() const {\n" - " return $name$_ != NULL;\n" + "$inline$ bool $classname$::has_$name$() const {\n" + " return !_is_default_instance_ && $name$_ != NULL;\n" "}\n"); } } @@ -570,7 +567,7 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { // Generate clear_$name$() printer->Print(vars, - "inline void $classname$::clear_$name$() {\n"); + "$inline$ void $classname$::clear_$name$() {\n"); printer->Indent(); @@ -599,7 +596,8 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { printer->Print("}\n"); // Generate type-specific accessors. - field_generators_.get(field).GenerateInlineAccessorDefinitions(printer); + field_generators_.get(field).GenerateInlineAccessorDefinitions(printer, + is_inline); printer->Print("\n"); } @@ -612,12 +610,13 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { vars["cap_oneof_name"] = ToUpper(descriptor_->oneof_decl(i)->name()); vars["classname"] = classname_; + vars["inline"] = is_inline ? "inline" : ""; printer->Print( vars, - "inline bool $classname$::has_$oneof_name$() const {\n" + "$inline$ bool $classname$::has_$oneof_name$() const {\n" " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n" "}\n" - "inline void $classname$::clear_has_$oneof_name$() {\n" + "$inline$ void $classname$::clear_has_$oneof_name$() {\n" " _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n" "}\n"); } @@ -1051,6 +1050,22 @@ GenerateClassDefinition(io::Printer* printer) { printer->Print(cached_size_decl.c_str()); need_to_emit_cached_size = false; } + } else { + // Without field presence, we need another way to disambiguate the default + // instance, because the default instance's submessage fields (if any) store + // pointers to the default instances of the submessages even when they + // aren't present. Alternatives to this approach might be to (i) use a + // tagged pointer on all message fields, setting a tag bit for "not really + // present, just default instance"; or (ii) comparing |this| against the + // return value from GeneratedMessageFactory::GetPrototype() in all + // has_$field$() calls. However, both of these options are much more + // expensive (in code size and CPU overhead) than just checking a field in + // the message. Long-term, the best solution would be to rearchitect the + // default instance design not to store pointers to submessage default + // instances, and have reflection get those some other way; but that change + // would have too much impact on proto2. + printer->Print( + "bool _is_default_instance_;\n"); } // Field members: @@ -1157,18 +1172,18 @@ GenerateClassDefinition(io::Printer* printer) { } void MessageGenerator:: -GenerateInlineMethods(io::Printer* printer) { +GenerateInlineMethods(io::Printer* printer, bool is_inline) { for (int i = 0; i < descriptor_->nested_type_count(); i++) { // map entry message doesn't need inline methods. Since map entry message // cannot be a top level class, we just need to avoid calling // GenerateInlineMethods here. if (IsMapEntryMessage(descriptor_->nested_type(i))) continue; - nested_generators_[i]->GenerateInlineMethods(printer); + nested_generators_[i]->GenerateInlineMethods(printer, is_inline); printer->Print(kThinSeparator); printer->Print("\n"); } - GenerateFieldAccessorDefinitions(printer); + GenerateFieldAccessorDefinitions(printer, is_inline); // Generate oneof_case() functions. for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { @@ -1178,9 +1193,10 @@ GenerateInlineMethods(io::Printer* printer) { descriptor_->oneof_decl(i)->name(), true); vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + vars["inline"] = is_inline ? "inline " : ""; printer->Print( vars, - "inline $class_name$::$camel_oneof_name$Case $class_name$::" + "$inline$$class_name$::$camel_oneof_name$Case $class_name$::" "$oneof_name$_case() const {\n" " return $class_name$::$camel_oneof_name$Case(" "_oneof_case_[$oneof_index$]);\n" @@ -1210,7 +1226,9 @@ GenerateDescriptorDeclarations(io::Printer* printer) { for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); printer->Print(" "); - if (IsStringOrMessage(field)) { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || + (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && + EffectiveStringCType(field) != FieldOptions::STRING)) { printer->Print("const "); } field_generators_.get(field).GeneratePrivateMembers(printer); @@ -1323,11 +1341,21 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) { if (UseUnknownFieldSet(descriptor_->file())) { printer->Print(vars, " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" - "$classname$, _internal_metadata_));\n"); + "$classname$, _internal_metadata_),\n"); + } else { + printer->Print(vars, + " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" + "$classname$, _arena_),\n"); + } + + // is_default_instance_ offset. + if (HasFieldPresence(descriptor_->file())) { + printer->Print(vars, + " -1);\n"); } else { printer->Print(vars, " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" - "$classname$, _arena_));\n"); + "$classname$, _is_default_instance_));\n"); } // Handle nested types. @@ -1369,8 +1397,8 @@ GenerateTypeRegistrations(io::Printer* printer) { " ::google::protobuf::internal::MapEntry<\n" " $key$,\n" " $val$,\n" - " $key_type$,\n" - " $val_type$,\n" + " $key_wire_type$,\n" + " $val_wire_type$,\n" " $default_enum_value$>::CreateDefaultInstance(\n" " $classname$_descriptor_));\n"); } @@ -1612,6 +1640,11 @@ GenerateSharedConstructorCode(io::Printer* printer) { "classname", classname_); printer->Indent(); + if (!HasFieldPresence(descriptor_->file())) { + printer->Print( + " _is_default_instance_ = false;\n"); + } + printer->Print(StrCat( uses_string_ ? "::google::protobuf::internal::GetEmptyString();\n" : "", "_cached_size_ = 0;\n").c_str()); @@ -1809,6 +1842,11 @@ GenerateStructors(io::Printer* printer) { "void $classname$::InitAsDefaultInstance() {\n", "classname", classname_); + if (!HasFieldPresence(descriptor_->file())) { + printer->Print( + " _is_default_instance_ = true;\n"); + } + // The default instance needs all of its embedded message pointers // cross-linked to other default instances. We can't do this initialization // in the constructor because some other default instances may not have been @@ -2002,17 +2040,16 @@ GenerateClear(io::Printer* printer) { // Step 2a: Greedily seek runs of fields that can be cleared by memset-to-0. // The generated code uses two macros to help it clear runs of fields: - // OFFSET_OF_FIELD_ computes the offset (in bytes) of a field in the Message. + // ZR_HELPER_(f1) - ZR_HELPER_(f0) computes the difference, in bytes, of the + // positions of two fields in the Message. // ZR_ zeroes a non-empty range of fields via memset. const char* macros = - "#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \\\n" - " &reinterpret_cast<$classname$*>(16)->f) - \\\n" - " reinterpret_cast<char*>(16))\n\n" - "#define ZR_(first, last) do { \\\n" - " size_t f = OFFSET_OF_FIELD_(first); \\\n" - " size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \\\n" - " ::memset(&first, 0, n); \\\n" - " } while (0)\n\n"; + "#define ZR_HELPER_(f) reinterpret_cast<char*>(\\\n" + " &reinterpret_cast<$classname$*>(16)->f)\n\n" + "#define ZR_(first, last) do {\\\n" + " ::memset(&first, 0,\\\n" + " ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\\\n" + "} while (0)\n\n"; for (int i = 0; i < runs_of_fields_.size(); i++) { const vector<string>& run = runs_of_fields_[i]; if (run.size() < 2) continue; @@ -2101,7 +2138,7 @@ GenerateClear(io::Printer* printer) { } if (macros_are_needed) { printer->Outdent(); - printer->Print("\n#undef OFFSET_OF_FIELD_\n#undef ZR_\n\n"); + printer->Print("\n#undef ZR_HELPER_\n#undef ZR_\n\n"); printer->Indent(); } @@ -2887,8 +2924,8 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { for (int i = 0; i < descriptor_->extension_range_count(); ++i) { sorted_extensions.push_back(descriptor_->extension_range(i)); } - sort(sorted_extensions.begin(), sorted_extensions.end(), - ExtensionRangeSorter()); + std::sort(sorted_extensions.begin(), sorted_extensions.end(), + ExtensionRangeSorter()); // Merge the fields and the extension ranges, both sorted by field number. int i, j; diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h index dfbc9af5..ea96581d 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.h +++ b/src/google/protobuf/compiler/cpp/cpp_message.h @@ -82,7 +82,7 @@ class MessageGenerator { // Generate definitions of inline methods (placed at the end of the header // file). - void GenerateInlineMethods(io::Printer* printer); + void GenerateInlineMethods(io::Printer* printer, bool is_inline); // Source file stuff. @@ -116,7 +116,7 @@ class MessageGenerator { private: // Generate declarations and definitions of accessors for fields. void GenerateFieldAccessorDeclarations(io::Printer* printer); - void GenerateFieldAccessorDefinitions(io::Printer* printer); + void GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline); // Generate the field offsets array. void GenerateOffsets(io::Printer* printer); diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc index b3cd0ba1..467b6bf6 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc @@ -85,76 +85,141 @@ GeneratePrivateMembers(io::Printer* printer) const { void MessageFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { + if (SupportsArenas(descriptor_)) { + printer->Print(variables_, + "private:\n" + "void _slow_mutable_$name$()$deprecation$;\n"); + if (SupportsArenas(descriptor_->message_type())) { + printer->Print(variables_, + "void _slow_set_allocated_$name$(\n" + " ::google::protobuf::Arena* message_arena, $type$** $name$)$deprecation$;\n"); + } + printer->Print(variables_, + "$type$* _slow_$release_name$()$deprecation$;\n" + "public:\n"); + } printer->Print(variables_, - "inline const $type$& $name$() const$deprecation$;\n" - "inline $type$* mutable_$name$()$deprecation$;\n" - "inline $type$* $release_name$()$deprecation$;\n" - "inline void set_allocated_$name$($type$* $name$)$deprecation$;\n"); + "const $type$& $name$() const$deprecation$;\n" + "$type$* mutable_$name$()$deprecation$;\n" + "$type$* $release_name$()$deprecation$;\n" + "void set_allocated_$name$($type$* $name$)$deprecation$;\n"); if (SupportsArenas(descriptor_)) { printer->Print(variables_, - "inline $type$* unsafe_arena_release_$name$()$deprecation$;\n" - "inline void unsafe_arena_set_allocated_$name$(\n" + "$type$* unsafe_arena_release_$name$()$deprecation$;\n" + "void unsafe_arena_set_allocated_$name$(\n" " $type$* $name$)$deprecation$;\n"); } } +void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions( + io::Printer* printer) const { + if (SupportsArenas(descriptor_)) { + printer->Print(variables_, + "void $classname$::_slow_mutable_$name$() {\n"); + if (SupportsArenas(descriptor_->message_type())) { + printer->Print(variables_, + " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n" + " GetArenaNoVirtual());\n"); + } else { + printer->Print(variables_, + " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n" + " GetArenaNoVirtual());\n"); + } + printer->Print(variables_, + "}\n" + "$type$* $classname$::_slow_$release_name$() {\n" + " if ($name$_ == NULL) {\n" + " return NULL;\n" + " } else {\n" + " $type$* temp = new $type$;\n" + " temp->MergeFrom(*$name$_);\n" + " $name$_ = NULL;\n" + " return temp;\n" + " }\n" + "}\n" + "$type$* $classname$::unsafe_arena_release_$name$() {\n" + " $clear_hasbit$\n" + " $type$* temp = $name$_;\n" + " $name$_ = NULL;\n" + " return temp;\n" + "}\n"); + if (SupportsArenas(descriptor_->message_type())) { + printer->Print(variables_, + "void $classname$::_slow_set_allocated_$name$(\n" + " ::google::protobuf::Arena* message_arena, $type$** $name$) {\n" + " if (message_arena != NULL && \n" + " ::google::protobuf::Arena::GetArena(*$name$) == NULL) {\n" + " message_arena->Own(*$name$);\n" + " } else if (message_arena !=\n" + " ::google::protobuf::Arena::GetArena(*$name$)) {\n" + " $type$* new_$name$ = \n" + " ::google::protobuf::Arena::CreateMessage< $type$ >(\n" + " message_arena);\n" + " new_$name$->CopyFrom(**$name$);\n" + " *$name$ = new_$name$;\n" + " }\n" + "}\n"); + } + printer->Print(variables_, + "void $classname$::unsafe_arena_set_allocated_$name$(\n" + " $type$* $name$) {\n" + // If we're not on an arena, free whatever we were holding before. + // (If we are on arena, we can just forget the earlier pointer.) + " if (GetArenaNoVirtual() == NULL) {\n" + " delete $name$_;\n" + " }\n" + " $name$_ = $name$;\n" + " if ($name$) {\n" + " $set_hasbit$\n" + " } else {\n" + " $clear_hasbit$\n" + " }\n" + " // @@protoc_insertion_point(field_unsafe_arena_set_allocated" + ":$full_name$)\n" + "}\n"); + } +} + void MessageFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline const $type$& $classname$::$name$() const {\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map<string, string> variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ const $type$& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n"); PrintHandlingOptionalStaticInitializers( - variables_, descriptor_->file(), printer, + variables, descriptor_->file(), printer, // With static initializers. " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n", // Without. " return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n"); if (SupportsArenas(descriptor_)) { - printer->Print(variables_, + printer->Print(variables, "}\n" - "inline $type$* $classname$::mutable_$name$() {\n" + "$inline$ $type$* $classname$::mutable_$name$() {\n" " $set_hasbit$\n" - " if ($name$_ == NULL) {\n"); - if (SupportsArenas(descriptor_->message_type())) { - printer->Print(variables_, - " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n" - " GetArenaNoVirtual());\n"); - } else { - printer->Print(variables_, - " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n" - " GetArenaNoVirtual());\n"); - } - printer->Print(variables_, " }\n" + " if ($name$_ == NULL) {\n" + " _slow_mutable_$name$();" + " }\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_;\n" "}\n" - "inline $type$* $classname$::$release_name$() {\n" + "$inline$ $type$* $classname$::$release_name$() {\n" " $clear_hasbit$\n" " if (GetArenaNoVirtual() != NULL) {\n" - " if ($name$_ == NULL) {\n" - " return NULL;\n" - " } else {\n" - " $type$* temp = new $type$;\n" - " temp->MergeFrom(*$name$_);\n" - " $name$_ = NULL;\n" - " return temp;\n" - " }\n" + " return _slow_$release_name$();\n" " } else {\n" " $type$* temp = $name$_;\n" " $name$_ = NULL;\n" " return temp;\n" " }\n" "}\n" - "inline $type$* $classname$::unsafe_arena_release_$name$() {\n" - " $clear_hasbit$\n" - " $type$* temp = $name$_;\n" - " $name$_ = NULL;\n" - " return temp;\n" - "}\n" - "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" - " if (GetArenaNoVirtual() == NULL) {\n" + "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n" + " ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n" + " if (message_arena == NULL) {\n" " delete $name$_;\n" " }\n" " if ($name$ != NULL) {\n"); @@ -164,26 +229,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { // so we might as well defer it. Otherwise, if incoming message is on a // different ownership domain (specific arena, or the heap) than we are, // copy to our arena (or heap, as the case may be). - printer->Print(variables_, - " if (GetArenaNoVirtual() != NULL && \n" - " ::google::protobuf::Arena::GetArena($name$) == NULL) {\n" - " GetArenaNoVirtual()->Own($name$);\n" - " } else if (GetArenaNoVirtual() !=\n" - " ::google::protobuf::Arena::GetArena($name$)) {\n" - " $type$* new_$name$ = \n" - " ::google::protobuf::Arena::CreateMessage< $type$ >(\n" - " GetArenaNoVirtual());\n" - " new_$name$->CopyFrom(*$name$);\n" - " $name$ = new_$name$;\n" - " }\n"); + printer->Print(variables, + " _slow_set_allocated_$name$(message_arena, &$name$);\n"); } else { - printer->Print(variables_, - " if (GetArenaNoVirtual() != NULL) {\n" - " GetArenaNoVirtual()->Own($name$);\n" + printer->Print(variables, + " if (message_arena != NULL) {\n" + " message_arena->Own($name$);\n" " }\n"); } - - printer->Print(variables_, + printer->Print(variables, " }\n" " $name$_ = $name$;\n" " if ($name$) {\n" @@ -192,27 +246,11 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $clear_hasbit$\n" " }\n" " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" - "}\n" - "inline void $classname$::unsafe_arena_set_allocated_$name$(\n" - " $type$* $name$) {\n" - // If we're not on an arena, free whatever we were holding before. - // (If we are on arena, we can just forget the earlier pointer.) - " if (GetArenaNoVirtual() == NULL) {\n" - " delete $name$_;\n" - " }\n" - " $name$_ = $name$;\n" - " if ($name$) {\n" - " $set_hasbit$\n" - " } else {\n" - " $clear_hasbit$\n" - " }\n" - " // @@protoc_insertion_point(field_unsafe_arena_set_allocated" - ":$full_name$)\n" "}\n"); } else { - printer->Print(variables_, + printer->Print(variables, "}\n" - "inline $type$* $classname$::mutable_$name$() {\n" + "$inline$ $type$* $classname$::mutable_$name$() {\n" " $set_hasbit$\n" " if ($name$_ == NULL) {\n" " $name$_ = new $type$;\n" @@ -220,17 +258,17 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_;\n" "}\n" - "inline $type$* $classname$::$release_name$() {\n" + "$inline$ $type$* $classname$::$release_name$() {\n" " $clear_hasbit$\n" " $type$* temp = $name$_;\n" " $name$_ = NULL;\n" " return temp;\n" "}\n" - "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" + "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n" " delete $name$_;\n"); if (SupportsArenas(descriptor_->message_type())) { - printer->Print(variables_, + printer->Print(variables, " if ($name$ != NULL && $name$->GetArena() != NULL) {\n" " $type$* new_$name$ = new $type$;\n" " new_$name$->CopyFrom(*$name$);\n" @@ -238,7 +276,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " }\n"); } - printer->Print(variables_, + printer->Print(variables, " $name$_ = $name$;\n" " if ($name$) {\n" " $set_hasbit$\n" @@ -328,35 +366,38 @@ MessageOneofFieldGenerator(const FieldDescriptor* descriptor, MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {} void MessageOneofFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map<string, string> variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - "inline const $type$& $classname$::$name$() const {\n" + printer->Print(variables, + "$inline$ const $type$& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return has_$name$() ? *$oneof_prefix$$name$_\n" " : $type$::default_instance();\n" "}\n" - "inline $type$* $classname$::mutable_$name$() {\n" + "$inline$ $type$* $classname$::mutable_$name$() {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n"); if (SupportsArenas(descriptor_->message_type())) { - printer->Print(variables_, + printer->Print(variables, " $oneof_prefix$$name$_ = \n" " ::google::protobuf::Arena::CreateMessage< $type$ >(\n" " GetArenaNoVirtual());\n"); } else { - printer->Print(variables_, + printer->Print(variables, " $oneof_prefix$$name$_ = \n" " ::google::protobuf::Arena::Create< $type$ >(\n" " GetArenaNoVirtual());\n"); } - printer->Print(variables_, + printer->Print(variables, " }\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $oneof_prefix$$name$_;\n" "}\n" - "inline $type$* $classname$::$release_name$() {\n" + "$inline$ $type$* $classname$::$release_name$() {\n" " if (has_$name$()) {\n" " clear_has_$oneof_name$();\n" " if (GetArenaNoVirtual() != NULL) {\n" @@ -375,7 +416,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " return NULL;\n" " }\n" "}\n" - "inline $type$* $classname$::unsafe_arena_release_$name$() {\n" + "$inline$ $type$* $classname$::unsafe_arena_release_$name$() {\n" " if (has_$name$()) {\n" " clear_has_$oneof_name$();\n" " $type$* temp = $oneof_prefix$$name$_;\n" @@ -385,12 +426,12 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " return NULL;\n" " }\n" "}\n" - "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" + "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n" " clear_$oneof_name$();\n" " if ($name$) {\n"); if (SupportsArenas(descriptor_->message_type())) { - printer->Print(variables_, + printer->Print(variables, // If incoming message is on the heap and we are on an arena, just Own() // it (see above). If it's on a different arena than we are or one of us // is on the heap, we make a copy to our arena/heap. @@ -406,19 +447,19 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $name$ = new_$name$;\n" " }\n"); } else { - printer->Print(variables_, + printer->Print(variables, " if (GetArenaNoVirtual() != NULL) {\n" " GetArenaNoVirtual()->Own($name$);\n" " }\n"); } - printer->Print(variables_, + printer->Print(variables, " set_has_$name$();\n" " $oneof_prefix$$name$_ = $name$;\n" " }\n" " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n" - "inline void $classname$::unsafe_arena_set_allocated_$name$(" + "$inline$ void $classname$::unsafe_arena_set_allocated_$name$(" "$type$* $name$) {\n" // We rely on the oneof clear method to free the earlier contents of this // oneof. We can directly use the pointer we're given to set the new @@ -432,13 +473,13 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { "$full_name$)\n" "}\n"); } else { - printer->Print(variables_, - "inline const $type$& $classname$::$name$() const {\n" + printer->Print(variables, + "$inline$ const $type$& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return has_$name$() ? *$oneof_prefix$$name$_\n" " : $type$::default_instance();\n" "}\n" - "inline $type$* $classname$::mutable_$name$() {\n" + "$inline$ $type$* $classname$::mutable_$name$() {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" @@ -447,7 +488,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $oneof_prefix$$name$_;\n" "}\n" - "inline $type$* $classname$::$release_name$() {\n" + "$inline$ $type$* $classname$::$release_name$() {\n" " if (has_$name$()) {\n" " clear_has_$oneof_name$();\n" " $type$* temp = $oneof_prefix$$name$_;\n" @@ -457,18 +498,18 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " return NULL;\n" " }\n" "}\n" - "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" + "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n" " clear_$oneof_name$();\n" " if ($name$) {\n"); if (SupportsArenas(descriptor_->message_type())) { - printer->Print(variables_, + printer->Print(variables, " if ($name$->GetArena() != NULL) {\n" " $type$* new_$name$ = new $type$;\n" " new_$name$->CopyFrom(*$name$);\n" " $name$ = new_$name$;\n" " }\n"); } - printer->Print(variables_, + printer->Print(variables, " set_has_$name$();\n" " $oneof_prefix$$name$_ = $name$;\n" " }\n" @@ -521,38 +562,41 @@ GeneratePrivateMembers(io::Printer* printer) const { void RepeatedMessageFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline const $type$& $name$(int index) const$deprecation$;\n" - "inline $type$* mutable_$name$(int index)$deprecation$;\n" - "inline $type$* add_$name$()$deprecation$;\n"); + "const $type$& $name$(int index) const$deprecation$;\n" + "$type$* mutable_$name$(int index)$deprecation$;\n" + "$type$* add_$name$()$deprecation$;\n"); printer->Print(variables_, - "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" + "const ::google::protobuf::RepeatedPtrField< $type$ >&\n" " $name$() const$deprecation$;\n" - "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n" + "::google::protobuf::RepeatedPtrField< $type$ >*\n" " mutable_$name$()$deprecation$;\n"); } void RepeatedMessageFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline const $type$& $classname$::$name$(int index) const {\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map<string, string> variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ const $type$& $classname$::$name$(int index) const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_.$cppget$(index);\n" "}\n" - "inline $type$* $classname$::mutable_$name$(int index) {\n" + "$inline$ $type$* $classname$::mutable_$name$(int index) {\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_.Mutable(index);\n" "}\n" - "inline $type$* $classname$::add_$name$() {\n" + "$inline$ $type$* $classname$::add_$name$() {\n" " // @@protoc_insertion_point(field_add:$full_name$)\n" " return $name$_.Add();\n" "}\n"); - printer->Print(variables_, - "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" + printer->Print(variables, + "$inline$ const ::google::protobuf::RepeatedPtrField< $type$ >&\n" "$classname$::$name$() const {\n" " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" - "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n" + "$inline$ ::google::protobuf::RepeatedPtrField< $type$ >*\n" "$classname$::mutable_$name$() {\n" " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h index 2dff3144..c1704fc1 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h @@ -53,7 +53,9 @@ class MessageFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; + void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; @@ -78,7 +80,9 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator { ~MessageOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; + void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {} void GenerateClearingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; @@ -96,7 +100,8 @@ class RepeatedMessageFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc index 9a2c930e..329eae32 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc @@ -117,18 +117,20 @@ GeneratePrivateMembers(io::Printer* printer) const { void PrimitiveFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline $type$ $name$() const$deprecation$;\n" - "inline void set_$name$($type$ value)$deprecation$;\n"); + "$type$ $name$() const$deprecation$;\n" + "void set_$name$($type$ value)$deprecation$;\n"); } void PrimitiveFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$() const {\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const { + map<string, string> variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ $type$ $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_;\n" "}\n" - "inline void $classname$::set_$name$($type$ value) {\n" + "$inline$ void $classname$::set_$name$($type$ value) {\n" " $set_hasbit$\n" " $name$_ = value;\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" @@ -204,16 +206,18 @@ PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {} void PrimitiveOneofFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$() const {\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const { + map<string, string> variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ $type$ $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " if (has_$name$()) {\n" " return $oneof_prefix$$name$_;\n" " }\n" " return $default$;\n" "}\n" - "inline void $classname$::set_$name$($type$ value) {\n" + "$inline$ void $classname$::set_$name$($type$ value) {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" @@ -282,38 +286,40 @@ GeneratePrivateMembers(io::Printer* printer) const { void RepeatedPrimitiveFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline $type$ $name$(int index) const$deprecation$;\n" - "inline void set_$name$(int index, $type$ value)$deprecation$;\n" - "inline void add_$name$($type$ value)$deprecation$;\n"); + "$type$ $name$(int index) const$deprecation$;\n" + "void set_$name$(int index, $type$ value)$deprecation$;\n" + "void add_$name$($type$ value)$deprecation$;\n"); printer->Print(variables_, - "inline const ::google::protobuf::RepeatedField< $type$ >&\n" + "const ::google::protobuf::RepeatedField< $type$ >&\n" " $name$() const$deprecation$;\n" - "inline ::google::protobuf::RepeatedField< $type$ >*\n" + "::google::protobuf::RepeatedField< $type$ >*\n" " mutable_$name$()$deprecation$;\n"); } void RepeatedPrimitiveFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$(int index) const {\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const { + map<string, string> variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ $type$ $classname$::$name$(int index) const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_.Get(index);\n" "}\n" - "inline void $classname$::set_$name$(int index, $type$ value) {\n" + "$inline$ void $classname$::set_$name$(int index, $type$ value) {\n" " $name$_.Set(index, value);\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" - "inline void $classname$::add_$name$($type$ value) {\n" + "$inline$ void $classname$::add_$name$($type$ value) {\n" " $name$_.Add(value);\n" " // @@protoc_insertion_point(field_add:$full_name$)\n" "}\n"); - printer->Print(variables_, - "inline const ::google::protobuf::RepeatedField< $type$ >&\n" + printer->Print(variables, + "$inline$ const ::google::protobuf::RepeatedField< $type$ >&\n" "$classname$::$name$() const {\n" " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" - "inline ::google::protobuf::RepeatedField< $type$ >*\n" + "$inline$ ::google::protobuf::RepeatedField< $type$ >*\n" "$classname$::mutable_$name$() {\n" " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h index 97b5e867..fcd7d684 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h @@ -53,7 +53,8 @@ class PrimitiveFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; @@ -78,7 +79,8 @@ class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator { ~PrimitiveOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; @@ -97,7 +99,8 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/cpp/cpp_service.cc b/src/google/protobuf/compiler/cpp/cpp_service.cc index a8f303da..226c2aa0 100644 --- a/src/google/protobuf/compiler/cpp/cpp_service.cc +++ b/src/google/protobuf/compiler/cpp/cpp_service.cc @@ -301,7 +301,7 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which, printer->Print(vars_, " default:\n" " GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n" - " return *reinterpret_cast< ::google::protobuf::Message*>(NULL);\n" + " return *static_cast< ::google::protobuf::Message*>(NULL);\n" " }\n" "}\n" "\n"); diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc index a7f95044..1a1bcd3d 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -127,7 +127,11 @@ GenerateAccessorDeclarations(io::Printer* printer) const { // files that applied the ctype. The field can still be accessed via the // reflection interface since the reflection interface is independent of // the string's underlying representation. - if (descriptor_->options().ctype() != FieldOptions::STRING) { + + bool unknown_ctype = + descriptor_->options().ctype() != EffectiveStringCType(descriptor_); + + if (unknown_ctype) { printer->Outdent(); printer->Print( " private:\n" @@ -136,23 +140,23 @@ GenerateAccessorDeclarations(io::Printer* printer) const { } printer->Print(variables_, - "inline const ::std::string& $name$() const$deprecation$;\n" - "inline void set_$name$(const ::std::string& value)$deprecation$;\n" - "inline void set_$name$(const char* value)$deprecation$;\n" - "inline void set_$name$(const $pointer_type$* value, size_t size)" + "const ::std::string& $name$() const$deprecation$;\n" + "void set_$name$(const ::std::string& value)$deprecation$;\n" + "void set_$name$(const char* value)$deprecation$;\n" + "void set_$name$(const $pointer_type$* value, size_t size)" "$deprecation$;\n" - "inline ::std::string* mutable_$name$()$deprecation$;\n" - "inline ::std::string* $release_name$()$deprecation$;\n" - "inline void set_allocated_$name$(::std::string* $name$)$deprecation$;\n"); + "::std::string* mutable_$name$()$deprecation$;\n" + "::std::string* $release_name$()$deprecation$;\n" + "void set_allocated_$name$(::std::string* $name$)$deprecation$;\n"); if (SupportsArenas(descriptor_)) { printer->Print(variables_, - "inline ::std::string* unsafe_arena_release_$name$()$deprecation$;\n" - "inline void unsafe_arena_set_allocated_$name$(\n" + "::std::string* unsafe_arena_release_$name$()$deprecation$;\n" + "void unsafe_arena_set_allocated_$name$(\n" " ::std::string* $name$)$deprecation$;\n"); } - if (descriptor_->options().ctype() != FieldOptions::STRING) { + if (unknown_ctype) { printer->Outdent(); printer->Print(" public:\n"); printer->Indent(); @@ -160,25 +164,28 @@ GenerateAccessorDeclarations(io::Printer* printer) const { } void StringFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map<string, string> variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - "inline const ::std::string& $classname$::$name$() const {\n" + printer->Print(variables, + "$inline$ const ::std::string& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_.Get($default_variable$);\n" "}\n" - "inline void $classname$::set_$name$(const ::std::string& value) {\n" + "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n" " $set_hasbit$\n" " $name$_.Set($default_variable$, value, GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" - "inline void $classname$::set_$name$(const char* value) {\n" + "$inline$ void $classname$::set_$name$(const char* value) {\n" " $set_hasbit$\n" " $name$_.Set($default_variable$, $string_piece$(value),\n" " GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n" - "inline " + "$inline$ " "void $classname$::set_$name$(const $pointer_type$* value,\n" " size_t size) {\n" " $set_hasbit$\n" @@ -186,22 +193,22 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" - "inline ::std::string* $classname$::mutable_$name$() {\n" + "$inline$ ::std::string* $classname$::mutable_$name$() {\n" " $set_hasbit$\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_.Mutable($default_variable$, GetArenaNoVirtual());\n" "}\n" - "inline ::std::string* $classname$::$release_name$() {\n" + "$inline$ ::std::string* $classname$::$release_name$() {\n" " $clear_hasbit$\n" " return $name$_.Release($default_variable$, GetArenaNoVirtual());\n" "}\n" - "inline ::std::string* $classname$::unsafe_arena_release_$name$() {\n" + "$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n" " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n" " $clear_hasbit$\n" " return $name$_.UnsafeArenaRelease($default_variable$,\n" " GetArenaNoVirtual());\n" "}\n" - "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" + "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n" " if ($name$ != NULL) {\n" " $set_hasbit$\n" " } else {\n" @@ -211,7 +218,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n" - "inline void $classname$::unsafe_arena_set_allocated_$name$(\n" + "$inline$ void $classname$::unsafe_arena_set_allocated_$name$(\n" " ::std::string* $name$) {\n" " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n" " if ($name$ != NULL) {\n" @@ -226,22 +233,22 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { "}\n"); } else { // No-arena case. - printer->Print(variables_, - "inline const ::std::string& $classname$::$name$() const {\n" + printer->Print(variables, + "$inline$ const ::std::string& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_.GetNoArena($default_variable$);\n" "}\n" - "inline void $classname$::set_$name$(const ::std::string& value) {\n" + "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n" " $set_hasbit$\n" " $name$_.SetNoArena($default_variable$, value);\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" - "inline void $classname$::set_$name$(const char* value) {\n" + "$inline$ void $classname$::set_$name$(const char* value) {\n" " $set_hasbit$\n" " $name$_.SetNoArena($default_variable$, $string_piece$(value));\n" " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n" - "inline " + "$inline$ " "void $classname$::set_$name$(const $pointer_type$* value, " "size_t size) {\n" " $set_hasbit$\n" @@ -249,16 +256,16 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $string_piece$(reinterpret_cast<const char*>(value), size));\n" " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" - "inline ::std::string* $classname$::mutable_$name$() {\n" + "$inline$ ::std::string* $classname$::mutable_$name$() {\n" " $set_hasbit$\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_.MutableNoArena($default_variable$);\n" "}\n" - "inline ::std::string* $classname$::$release_name$() {\n" + "$inline$ ::std::string* $classname$::$release_name$() {\n" " $clear_hasbit$\n" " return $name$_.ReleaseNoArena($default_variable$);\n" "}\n" - "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" + "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n" " if ($name$ != NULL) {\n" " $set_hasbit$\n" " } else {\n" @@ -422,17 +429,20 @@ StringOneofFieldGenerator(const FieldDescriptor* descriptor, StringOneofFieldGenerator::~StringOneofFieldGenerator() {} void StringOneofFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map<string, string> variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - "inline const ::std::string& $classname$::$name$() const {\n" + printer->Print(variables, + "$inline$ const ::std::string& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " if (has_$name$()) {\n" " return $oneof_prefix$$name$_.Get($default_variable$);\n" " }\n" " return *$default_variable$;\n" "}\n" - "inline void $classname$::set_$name$(const ::std::string& value) {\n" + "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" @@ -442,7 +452,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" - "inline void $classname$::set_$name$(const char* value) {\n" + "$inline$ void $classname$::set_$name$(const char* value) {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" @@ -452,7 +462,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $string_piece$(value), GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n" - "inline " + "$inline$ " "void $classname$::set_$name$(const $pointer_type$* value,\n" " size_t size) {\n" " if (!has_$name$()) {\n" @@ -465,7 +475,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" - "inline ::std::string* $classname$::mutable_$name$() {\n" + "$inline$ ::std::string* $classname$::mutable_$name$() {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" @@ -475,7 +485,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" "}\n" - "inline ::std::string* $classname$::$release_name$() {\n" + "$inline$ ::std::string* $classname$::$release_name$() {\n" " if (has_$name$()) {\n" " clear_has_$oneof_name$();\n" " return $oneof_prefix$$name$_.Release($default_variable$,\n" @@ -484,7 +494,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " return NULL;\n" " }\n" "}\n" - "inline ::std::string* $classname$::unsafe_arena_release_$name$() {\n" + "$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n" " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n" " if (has_$name$()) {\n" " clear_has_$oneof_name$();\n" @@ -494,7 +504,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " return NULL;\n" " }\n" "}\n" - "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" + "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n" " if (!has_$name$()) {\n" " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" " }\n" @@ -506,7 +516,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " }\n" " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n" - "inline void $classname$::unsafe_arena_set_allocated_$name$(" + "$inline$ void $classname$::unsafe_arena_set_allocated_$name$(" "::std::string* $name$) {\n" " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n" " if (!has_$name$()) {\n" @@ -522,15 +532,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { "}\n"); } else { // No-arena case. - printer->Print(variables_, - "inline const ::std::string& $classname$::$name$() const {\n" + printer->Print(variables, + "$inline$ const ::std::string& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " if (has_$name$()) {\n" " return $oneof_prefix$$name$_.GetNoArena($default_variable$);\n" " }\n" " return *$default_variable$;\n" "}\n" - "inline void $classname$::set_$name$(const ::std::string& value) {\n" + "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" @@ -540,7 +550,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $oneof_prefix$$name$_.SetNoArena($default_variable$, value);\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" - "inline void $classname$::set_$name$(const char* value) {\n" + "$inline$ void $classname$::set_$name$(const char* value) {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" @@ -550,7 +560,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $string_piece$(value));\n" " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n" - "inline " + "$inline$ " "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" @@ -561,7 +571,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " reinterpret_cast<const char*>(value), size));\n" " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" - "inline ::std::string* $classname$::mutable_$name$() {\n" + "$inline$ ::std::string* $classname$::mutable_$name$() {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" @@ -570,7 +580,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $oneof_prefix$$name$_.MutableNoArena($default_variable$);\n" "}\n" - "inline ::std::string* $classname$::$release_name$() {\n" + "$inline$ ::std::string* $classname$::$release_name$() {\n" " if (has_$name$()) {\n" " clear_has_$oneof_name$();\n" " return $oneof_prefix$$name$_.ReleaseNoArena($default_variable$);\n" @@ -578,7 +588,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " return NULL;\n" " }\n" "}\n" - "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" + "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n" " if (!has_$name$()) {\n" " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" " }\n" @@ -613,8 +623,7 @@ GenerateSwappingCode(io::Printer* printer) const { void StringOneofFieldGenerator:: GenerateConstructorCode(io::Printer* printer) const { printer->Print(variables_, - " const_cast< ::google::protobuf::internal::ArenaStringPtr*>(" - "&$classname$_default_oneof_instance_->$name$_)->UnsafeSetDefault(" + " $classname$_default_oneof_instance_->$name$_.UnsafeSetDefault(" "$default_variable$);\n"); } @@ -671,7 +680,10 @@ GeneratePrivateMembers(io::Printer* printer) const { void RepeatedStringFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { // See comment above about unknown ctypes. - if (descriptor_->options().ctype() != FieldOptions::STRING) { + bool unknown_ctype = + descriptor_->options().ctype() != EffectiveStringCType(descriptor_); + + if (unknown_ctype) { printer->Outdent(); printer->Print( " private:\n" @@ -680,26 +692,26 @@ GenerateAccessorDeclarations(io::Printer* printer) const { } printer->Print(variables_, - "inline const ::std::string& $name$(int index) const$deprecation$;\n" - "inline ::std::string* mutable_$name$(int index)$deprecation$;\n" - "inline void set_$name$(int index, const ::std::string& value)$deprecation$;\n" - "inline void set_$name$(int index, const char* value)$deprecation$;\n" - "inline " + "const ::std::string& $name$(int index) const$deprecation$;\n" + "::std::string* mutable_$name$(int index)$deprecation$;\n" + "void set_$name$(int index, const ::std::string& value)$deprecation$;\n" + "void set_$name$(int index, const char* value)$deprecation$;\n" + "" "void set_$name$(int index, const $pointer_type$* value, size_t size)" "$deprecation$;\n" - "inline ::std::string* add_$name$()$deprecation$;\n" - "inline void add_$name$(const ::std::string& value)$deprecation$;\n" - "inline void add_$name$(const char* value)$deprecation$;\n" - "inline void add_$name$(const $pointer_type$* value, size_t size)" + "::std::string* add_$name$()$deprecation$;\n" + "void add_$name$(const ::std::string& value)$deprecation$;\n" + "void add_$name$(const char* value)$deprecation$;\n" + "void add_$name$(const $pointer_type$* value, size_t size)" "$deprecation$;\n"); printer->Print(variables_, - "inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const" + "const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const" "$deprecation$;\n" - "inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()" + "::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()" "$deprecation$;\n"); - if (descriptor_->options().ctype() != FieldOptions::STRING) { + if (unknown_ctype) { printer->Outdent(); printer->Print(" public:\n"); printer->Indent(); @@ -707,54 +719,57 @@ GenerateAccessorDeclarations(io::Printer* printer) const { } void RepeatedStringFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline const ::std::string& $classname$::$name$(int index) const {\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map<string, string> variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ const ::std::string& $classname$::$name$(int index) const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_.$cppget$(index);\n" "}\n" - "inline ::std::string* $classname$::mutable_$name$(int index) {\n" + "$inline$ ::std::string* $classname$::mutable_$name$(int index) {\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_.Mutable(index);\n" "}\n" - "inline void $classname$::set_$name$(int index, const ::std::string& value) {\n" + "$inline$ void $classname$::set_$name$(int index, const ::std::string& value) {\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" " $name$_.Mutable(index)->assign(value);\n" "}\n" - "inline void $classname$::set_$name$(int index, const char* value) {\n" + "$inline$ void $classname$::set_$name$(int index, const char* value) {\n" " $name$_.Mutable(index)->assign(value);\n" " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n" - "inline void " + "$inline$ void " "$classname$::set_$name$" "(int index, const $pointer_type$* value, size_t size) {\n" " $name$_.Mutable(index)->assign(\n" " reinterpret_cast<const char*>(value), size);\n" " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" - "inline ::std::string* $classname$::add_$name$() {\n" + "$inline$ ::std::string* $classname$::add_$name$() {\n" " return $name$_.Add();\n" "}\n" - "inline void $classname$::add_$name$(const ::std::string& value) {\n" + "$inline$ void $classname$::add_$name$(const ::std::string& value) {\n" " $name$_.Add()->assign(value);\n" " // @@protoc_insertion_point(field_add:$full_name$)\n" "}\n" - "inline void $classname$::add_$name$(const char* value) {\n" + "$inline$ void $classname$::add_$name$(const char* value) {\n" " $name$_.Add()->assign(value);\n" " // @@protoc_insertion_point(field_add_char:$full_name$)\n" "}\n" - "inline void " + "$inline$ void " "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n" " $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n" " // @@protoc_insertion_point(field_add_pointer:$full_name$)\n" "}\n"); - printer->Print(variables_, - "inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n" + printer->Print(variables, + "$inline$ const ::google::protobuf::RepeatedPtrField< ::std::string>&\n" "$classname$::$name$() const {\n" " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" - "inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n" + "$inline$ ::google::protobuf::RepeatedPtrField< ::std::string>*\n" "$classname$::mutable_$name$() {\n" " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h index 0a5ca440..d1f19cd9 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h @@ -54,7 +54,8 @@ class StringFieldGenerator : public FieldGenerator { void GeneratePrivateMembers(io::Printer* printer) const; void GenerateStaticMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; @@ -83,7 +84,8 @@ class StringOneofFieldGenerator : public StringFieldGenerator { ~StringOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; @@ -103,7 +105,8 @@ class RepeatedStringFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto index 4fa3c144..9f63155b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto +++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto @@ -131,6 +131,24 @@ message TestConflictingSymbolNamesExtension { // NO_PROTO3 } // NO_PROTO3 } // NO_PROTO3 +message TestConflictingEnumNames { + enum NestedConflictingEnum { + and = 1; + class = 2; + int = 3; + typedef = 4; + XOR = 5; + } + + optional NestedConflictingEnum conflicting_enum = 1; +} + +enum ConflictingEnum { + NOT_EQ = 1; + volatile = 2; + return = 3; +} + message DummyMessage {} service TestConflictingMethodNames { diff --git a/src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto b/src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto new file mode 100644 index 00000000..cb6ca1b1 --- /dev/null +++ b/src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto @@ -0,0 +1,43 @@ +// 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. + +// Test that proto2 compiler can generate valid code when the enum value +// is INT_MAX. Note that this is a compile-only test and this proto is not +// referenced in any C++ code. +syntax = "proto2"; + +package protobuf_unittest; + +message TestLargeEnumValue { + enum EnumWithLargeValue { + VALUE_1 = 1; + VALUE_MAX = 0x7fffffff; + } +} diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index 20fcfa62..cc758cf5 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -153,6 +153,7 @@ TEST(GeneratedMessageTest, Defaults) { &message.optional_import_message()); } +#ifndef PROTOBUF_USE_DLLS TEST(GeneratedMessageTest, Int32StringConversion) { EXPECT_EQ("971", Int32ToString(971)); EXPECT_EQ("(~0x7fffffff)", Int32ToString(kint32min)); @@ -165,6 +166,7 @@ TEST(GeneratedMessageTest, Int64StringConversion) { EXPECT_EQ("GOOGLE_LONGLONG(~0x7fffffffffffffff)", Int64ToString(kint64min)); EXPECT_EQ("GOOGLE_LONGLONG(9223372036854775807)", Int64ToString(kint64max)); } +#endif // !PROTOBUF_USE_DLLS TEST(GeneratedMessageTest, FloatingPointDefaults) { const unittest::TestExtremeDefaultValues& extreme_default = @@ -792,6 +794,21 @@ TEST(GeneratedMessageTest, TestConflictingSymbolNames) { message.GetExtension(ExtensionMessage::repeated_int32_ext, 0)); } +TEST(GeneratedMessageTest, TestConflictingEnumNames) { + protobuf_unittest::TestConflictingEnumNames message; + message.set_conflicting_enum(protobuf_unittest::TestConflictingEnumNames_NestedConflictingEnum_and_); + EXPECT_EQ(1, message.conflicting_enum()); + message.set_conflicting_enum(protobuf_unittest::TestConflictingEnumNames_NestedConflictingEnum_XOR); + EXPECT_EQ(5, message.conflicting_enum()); + + + protobuf_unittest::ConflictingEnum conflicting_enum; + conflicting_enum = protobuf_unittest::NOT_EQ; + EXPECT_EQ(1, conflicting_enum); + conflicting_enum = protobuf_unittest::return_; + EXPECT_EQ(3, conflicting_enum); +} + #ifndef PROTOBUF_TEST_NO_DESCRIPTORS TEST(GeneratedMessageTest, TestOptimizedForSize) { diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h index e8d6f3a2..1cf360c1 100644 --- a/src/google/protobuf/compiler/java/java_field.h +++ b/src/google/protobuf/compiler/java/java_field.h @@ -83,6 +83,7 @@ class ImmutableFieldGenerator { virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer) const = 0; + virtual void GenerateStaticInitializationCode(io::Printer* printer) const {} virtual void GenerateEqualsCode(io::Printer* printer) const = 0; virtual void GenerateHashCode(io::Printer* printer) const = 0; diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc index 23685385..e24894b1 100644 --- a/src/google/protobuf/compiler/java/java_helpers.cc +++ b/src/google/protobuf/compiler/java/java_helpers.cc @@ -690,8 +690,8 @@ const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { for (int i = 0; i < descriptor->field_count(); i++) { fields[i] = descriptor->field(i); } - sort(fields, fields + descriptor->field_count(), - FieldOrderingByNumber()); + std::sort(fields, fields + descriptor->field_count(), + FieldOrderingByNumber()); return fields; } diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h index d957fdc4..62efbefa 100644 --- a/src/google/protobuf/compiler/java/java_helpers.h +++ b/src/google/protobuf/compiler/java/java_helpers.h @@ -297,6 +297,16 @@ struct ExtensionRangeOrdering { // and return it. The caller should delete the returned array. const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor); +// Does this message class have any packed fields? +inline bool HasPackedFields(const Descriptor* descriptor) { + for (int i = 0; i < descriptor->field_count(); i++) { + if (descriptor->field(i)->is_packed()) { + return true; + } + } + return false; +} + // Check a message type and its sub-message types recursively to see if any of // them has a required field. Return true if a required field is found. bool HasRequiredFields(const Descriptor* descriptor); diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field.cc b/src/google/protobuf/compiler/java/java_lazy_message_field.cc index 21cab7db..6e29a40b 100644 --- a/src/google/protobuf/compiler/java/java_lazy_message_field.cc +++ b/src/google/protobuf/compiler/java/java_lazy_message_field.cc @@ -243,9 +243,8 @@ GenerateBuildingCode(io::Printer* printer) const { "}\n"); printer->Print(variables_, - "result.$name$_.setByteString(\n" - " $name$_.toByteString(),\n" - " $name$_.getExtensionRegistry());\n"); + "result.$name$_.set(\n" + " $name$_);\n"); } void ImmutableLazyMessageFieldGenerator:: @@ -425,9 +424,8 @@ GenerateBuildingCode(io::Printer* printer) const { printer->Print(variables_, "result.$oneof_name$_ = new $lazy_type$();\n" - "(($lazy_type$) result.$oneof_name$_).setByteString(\n" - " (($lazy_type$) $oneof_name$_).toByteString(),\n" - " (($lazy_type$) $oneof_name$_).getExtensionRegistry());\n"); + "(($lazy_type$) result.$oneof_name$_).set(\n" + " (($lazy_type$) $oneof_name$_));\n"); printer->Outdent(); printer->Print("}\n"); } diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc index 2986f51f..cf1ef589 100644 --- a/src/google/protobuf/compiler/java/java_map_field.cc +++ b/src/google/protobuf/compiler/java/java_map_field.cc @@ -198,25 +198,38 @@ GenerateInterfaceMembers(io::Printer* printer) const { } void ImmutableMapFieldGenerator:: +GenerateStaticInitializationCode(io::Printer* printer) const { + printer->Print( + variables_, + "$name$DefaultEntry =\n" + " com.google.protobuf.MapEntry$lite$\n" + " .<$type_parameters$>newDefaultInstance(\n" + " $descriptor$\n" + " $key_wire_type$,\n" + " $key_default_value$,\n" + " $value_wire_type$,\n" + " $value_default_value$);\n" + "\n"); +} + +void ImmutableMapFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print( variables_, "private static final com.google.protobuf.MapEntry$lite$<\n" - " $type_parameters$> $name$DefaultEntry =\n" - " com.google.protobuf.MapEntry$lite$\n" - " .<$type_parameters$>newDefaultInstance(\n" - " $descriptor$\n" - " $key_wire_type$,\n" - " $key_default_value$,\n" - " $value_wire_type$,\n" - " $value_default_value$);\n"); + " $type_parameters$> $name$DefaultEntry;\n"); printer->Print( variables_, "private com.google.protobuf.MapField$lite$<\n" - " $type_parameters$> $name$_ =\n" - " com.google.protobuf.MapField$lite$.emptyMapField(\n" - " $map_field_parameter$);\n" - "\n"); + " $type_parameters$> $name$_;\n" + "private com.google.protobuf.MapField$lite$<$type_parameters$>\n" + "internalGet$capitalized_name$() {\n" + " if ($name$_ == null) {\n" + " return com.google.protobuf.MapField$lite$.emptyMapField(\n" + " $map_field_parameter$);\n" + " }\n" + " return $name$_;\n" + "}\n"); if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { printer->Print( variables_, @@ -233,7 +246,7 @@ GenerateMembers(io::Printer* printer) const { "$deprecation$\n" "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" "get$capitalized_name$Value() {\n" - " return $name$_.getMap();\n" + " return internalGet$capitalized_name$().getMap();\n" "}\n"); } WriteFieldDocComment(printer, descriptor_); @@ -244,7 +257,8 @@ GenerateMembers(io::Printer* printer) const { "get$capitalized_name$() {\n" " return new com.google.protobuf.Internal.MapAdapter<\n" " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n" - " $name$_.getMap(), $name$ValueConverter);\n" + " internalGet$capitalized_name$().getMap(),\n" + " $name$ValueConverter);\n" "}\n"); } else { WriteFieldDocComment(printer, descriptor_); @@ -252,7 +266,7 @@ GenerateMembers(io::Printer* printer) const { variables_, "$deprecation$\n" "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n" - " return $name$_.getMap();\n" + " return internalGet$capitalized_name$().getMap();\n" "}\n"); } } @@ -262,10 +276,24 @@ GenerateBuilderMembers(io::Printer* printer) const { printer->Print( variables_, "private com.google.protobuf.MapField$lite$<\n" - " $type_parameters$> $name$_ =\n" - " com.google.protobuf.MapField$lite$.newMapField(\n" - " $map_field_parameter$);\n" - "\n"); + " $type_parameters$> $name$_;\n" + "private com.google.protobuf.MapField$lite$<$type_parameters$>\n" + "internalGet$capitalized_name$() {\n" + " if ($name$_ == null) {\n" + " return com.google.protobuf.MapField$lite$.emptyMapField(\n" + " $map_field_parameter$);\n" + " }\n" + " return $name$_;\n" + "}\n" + "private com.google.protobuf.MapField$lite$<$type_parameters$>\n" + "internalGetMutable$capitalized_name$() {\n" + " $on_changed$;\n" + " if ($name$_ == null) {\n" + " $name$_ = com.google.protobuf.MapField$lite$.newMapField(\n" + " $map_field_parameter$);\n" + " }\n" + " return $name$_;\n" + "}\n"); if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { WriteFieldDocComment(printer, descriptor_); printer->Print( @@ -275,7 +303,8 @@ GenerateBuilderMembers(io::Printer* printer) const { "get$capitalized_name$() {\n" " return new com.google.protobuf.Internal.MapAdapter<\n" " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n" - " $name$_.getMap(), $name$ValueConverter);\n" + " internalGet$capitalized_name$().getMap(),\n" + " $name$ValueConverter);\n" "}\n"); WriteFieldDocComment(printer, descriptor_); printer->Print( @@ -283,10 +312,10 @@ GenerateBuilderMembers(io::Printer* printer) const { "$deprecation$\n" "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" "getMutable$capitalized_name$() {\n" - " $on_changed$\n" " return new com.google.protobuf.Internal.MapAdapter<\n" " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n" - " $name$_.getMutableMap(), $name$ValueConverter);\n" + " internalGetMutable$capitalized_name$().getMutableMap(),\n" + " $name$ValueConverter);\n" "}\n"); if (SupportUnknownEnumValue(descriptor_->file())) { WriteFieldDocComment(printer, descriptor_); @@ -295,7 +324,7 @@ GenerateBuilderMembers(io::Printer* printer) const { "$deprecation$\n" "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" "get$capitalized_name$Value() {\n" - " return $name$_.getMap();\n" + " return internalGet$capitalized_name$().getMap();\n" "}\n"); WriteFieldDocComment(printer, descriptor_); printer->Print( @@ -303,8 +332,7 @@ GenerateBuilderMembers(io::Printer* printer) const { "$deprecation$\n" "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" "getMutable$capitalized_name$Value() {\n" - " $on_changed$\n" - " return $name$_.getMutableMap();\n" + " return internalGetMutable$capitalized_name$().getMutableMap();\n" "}\n"); } } else { @@ -312,15 +340,14 @@ GenerateBuilderMembers(io::Printer* printer) const { printer->Print( variables_, "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n" - " return $name$_.getMap();\n" + " return internalGet$capitalized_name$().getMap();\n" "}\n"); WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, "public java.util.Map<$type_parameters$>\n" "getMutable$capitalized_name$() {\n" - " $on_changed$\n" - " return $name$_.getMutableMap();\n" + " return internalGetMutable$capitalized_name$().getMutableMap();\n" "}\n"); } } @@ -339,14 +366,15 @@ void ImmutableMapFieldGenerator:: GenerateBuilderClearCode(io::Printer* printer) const { printer->Print( variables_, - "$name$_.clear();\n"); + "internalGetMutable$capitalized_name$().clear();\n"); } void ImmutableMapFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { printer->Print( variables_, - "$name$_.mergeFrom(other.$name$_);\n"); + "internalGetMutable$capitalized_name$().mergeFrom(\n" + " other.internalGet$capitalized_name$());\n"); } void ImmutableMapFieldGenerator:: @@ -356,7 +384,7 @@ GenerateBuildingCode(io::Printer* printer) const { // We do a copy of the map field to ensure that the built result is // immutable. Implementation of this copy() method can do copy-on-write // to defer this copy until further modifications are made on the field. - "result.$name$_ = $name$_.copy();\n"); + "result.$name$_ = internalGet$capitalized_name$().copy();\n"); } void ImmutableMapFieldGenerator:: @@ -402,7 +430,7 @@ GenerateSerializationCode(io::Printer* printer) const { printer->Print( variables_, "for (java.util.Map.Entry<$type_parameters$> entry\n" - " : $name$_.getMap().entrySet()) {\n" + " : internalGet$capitalized_name$().getMap().entrySet()) {\n" " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n" " $name$ = $name$DefaultEntry.newBuilderForType()\n" " .setKey(entry.getKey())\n" @@ -417,7 +445,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print( variables_, "for (java.util.Map.Entry<$type_parameters$> entry\n" - " : $name$_.getMap().entrySet()) {\n" + " : internalGet$capitalized_name$().getMap().entrySet()) {\n" " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n" " $name$ = $name$DefaultEntry.newBuilderForType()\n" " .setKey(entry.getKey())\n" @@ -432,16 +460,17 @@ void ImmutableMapFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { printer->Print( variables_, - "result = result && $name$_.equals(other.$name$_);\n"); + "result = result && internalGet$capitalized_name$().equals(\n" + " other.internalGet$capitalized_name$());\n"); } void ImmutableMapFieldGenerator:: GenerateHashCode(io::Printer* printer) const { printer->Print( variables_, - "if (!$name$_.getMap().isEmpty()) {\n" + "if (!internalGet$capitalized_name$().getMap().isEmpty()) {\n" " hash = (37 * hash) + $constant_name$;\n" - " hash = (53 * hash) + $name$_.hashCode();\n" + " hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n" "}\n"); } diff --git a/src/google/protobuf/compiler/java/java_map_field.h b/src/google/protobuf/compiler/java/java_map_field.h index 80a94f45..3e6dd973 100644 --- a/src/google/protobuf/compiler/java/java_map_field.h +++ b/src/google/protobuf/compiler/java/java_map_field.h @@ -60,6 +60,7 @@ class ImmutableMapFieldGenerator : public ImmutableFieldGenerator { void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateStaticInitializationCode(io::Printer* printer) const; void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index ed94d6e4..63df10b4 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -242,7 +242,8 @@ void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) { "public interface $classname$OrBuilder extends \n" " $extra_interfaces$\n" " com.google.protobuf.GeneratedMessageLite.\n" - " ExtendableMessageOrBuilder<$classname$> {\n", + " ExtendableMessageOrBuilder<\n" + " $classname$, $classname$.Builder> {\n", "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), "classname", descriptor_->name()); } @@ -293,22 +294,41 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { // The builder_type stores the super type name of the nested Builder class. string builder_type; if (descriptor_->extension_range_count() > 0) { - printer->Print(variables, - "public $static$final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessage$lite$.ExtendableMessage<\n" - " $classname$> implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n"); + if (HasDescriptorMethods(descriptor_)) { + printer->Print(variables, + "public $static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n" + " $classname$> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n"); + } else { + printer->Print(variables, + "public $static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n" + " $classname$, $classname$.Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n"); + } builder_type = strings::Substitute( - "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>", - name_resolver_->GetImmutableClassName(descriptor_), - variables["lite"]); + "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>", + name_resolver_->GetImmutableClassName(descriptor_), + variables["lite"]); } else { - printer->Print(variables, - "public $static$final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessage$lite$ implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n"); + if (HasDescriptorMethods(descriptor_)) { + printer->Print(variables, + "public $static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessage implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n"); + } else { + printer->Print(variables, + "public $static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite<\n" + " $classname$, $classname$.Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n"); + } + builder_type = strings::Substitute( "com.google.protobuf.GeneratedMessage$0.Builder", variables["lite"]); @@ -357,7 +377,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { GenerateParsingConstructor(printer); } - GenerateDescriptorMethods(printer); + GenerateDescriptorMethods(printer, false); GenerateParser(printer); // Nested types @@ -489,7 +509,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { // Carefully initialize the default instance in such a way that it doesn't // conflict with other initialization. printer->Print( - "private static final $classname$ defaultInstance;", + "private static final $classname$ defaultInstance;\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); if (HasDescriptorMethods(descriptor_)) { printer->Print( @@ -502,15 +522,11 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { // LITE_RUNTIME only has one constructor. printer->Print( "static {\n" - " try {\n" - " defaultInstance = new $classname$(\n" - " com.google.protobuf.Internal\n" - " .EMPTY_CODED_INPUT_STREAM,\n" - " com.google.protobuf.ExtensionRegistryLite\n" - " .getEmptyRegistry());\n" - " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" - " throw new ExceptionInInitializerError(e);\n" - " }\n" + " defaultInstance = new $classname$(\n" + " com.google.protobuf.Internal\n" + " .EMPTY_CODED_INPUT_STREAM,\n" + " com.google.protobuf.ExtensionRegistryLite\n" + " .getEmptyRegistry());\n" "}\n" "\n", "classname", descriptor_->name()); @@ -519,12 +535,30 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { "public static $classname$ getDefaultInstance() {\n" " return defaultInstance;\n" "}\n" - "\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + if (HasDescriptorMethods(descriptor_)) { + // LITE_RUNTIME implements this at the GeneratedMessageLite level. + printer->Print( "public $classname$ getDefaultInstanceForType() {\n" " return defaultInstance;\n" "}\n" "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } else { + // LITE_RUNTIME uses this to implement the *ForType methods at the + // GeneratedMessageLite level. + printer->Print( + "static {" + " com.google.protobuf.GeneratedMessageLite.onLoad(\n" + " $classname$.class, new com.google.protobuf.GeneratedMessageLite\n" + " .PrototypeHolder<$classname$, Builder>(\n" + " defaultInstance, PARSER));" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } // Extensions must be declared after the defaultInstance is initialized // because the defaultInstance is used by the extension to lazily retrieve @@ -534,6 +568,19 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { .Generate(printer); } + // Some fields also have static members that must be initialized after we + // have the default instance available. + printer->Print( + "static {\n"); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateStaticInitializationCode(printer); + } + printer->Outdent(); + printer->Print( + "}\n"); + printer->Outdent(); printer->Print("}\n\n"); } @@ -550,37 +597,55 @@ GenerateMessageSerializationMethods(io::Printer* printer) { for (int i = 0; i < descriptor_->extension_range_count(); ++i) { sorted_extensions.push_back(descriptor_->extension_range(i)); } - sort(sorted_extensions.begin(), sorted_extensions.end(), - ExtensionRangeOrdering()); + std::sort(sorted_extensions.begin(), sorted_extensions.end(), + ExtensionRangeOrdering()); printer->Print( "public void writeTo(com.google.protobuf.CodedOutputStream output)\n" " throws java.io.IOException {\n"); printer->Indent(); - // writeTo(CodedOutputStream output) might be invoked without - // getSerializedSize() ever being called, but we need the memoized - // sizes in case this message has packed fields. Rather than emit checks for - // each packed field, just call getSerializedSize() up front for all messages. - // In most cases, getSerializedSize() will have already been called anyway by - // one of the wrapper writeTo() methods, making this call cheap. - printer->Print( - "getSerializedSize();\n"); + if (HasPackedFields(descriptor_)) { + // writeTo(CodedOutputStream output) might be invoked without + // getSerializedSize() ever being called, but we need the memoized + // sizes in case this message has packed fields. Rather than emit checks for + // each packed field, just call getSerializedSize() up front. + // In most cases, getSerializedSize() will have already been called anyway + // by one of the wrapper writeTo() methods, making this call cheap. + printer->Print( + "getSerializedSize();\n"); + } if (descriptor_->extension_range_count() > 0) { if (descriptor_->options().message_set_wire_format()) { - printer->Print( - "com.google.protobuf.GeneratedMessage$lite$\n" - " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n" - " newMessageSetExtensionWriter();\n", - "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "com.google.protobuf.GeneratedMessage\n" + " .ExtendableMessage<$classname$>.ExtensionWriter\n" + " extensionWriter = newMessageSetExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } else { + printer->Print( + "com.google.protobuf.GeneratedMessageLite\n" + " .ExtendableMessage<$classname$, $classname$.Builder>\n" + " .ExtensionWriter extensionWriter =\n" + " newMessageSetExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } } else { - printer->Print( - "com.google.protobuf.GeneratedMessage$lite$\n" - " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n" - " newExtensionWriter();\n", - "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "com.google.protobuf.GeneratedMessage\n" + " .ExtendableMessage<$classname$>.ExtensionWriter\n" + " extensionWriter = newExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } else { + printer->Print( + "com.google.protobuf.GeneratedMessageLite\n" + " .ExtendableMessage<$classname$, $classname$.Builder>\n" + " .ExtensionWriter extensionWriter =\n" + " newExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } } } @@ -735,13 +800,23 @@ void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange( // =================================================================== void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { + if (HasDescriptorMethods(descriptor_)) { + // LITE_RUNTIME implements this at the GeneratedMessageLite level. + printer->Print( + "public Builder newBuilderForType() { return newBuilder(); }\n"); + } + printer->Print( - "public static Builder newBuilder() { return new Builder(); }\n" - "public Builder newBuilderForType() { return newBuilder(); }\n" + "public static Builder newBuilder() {\n" + " return defaultInstance.toBuilder();\n" + "}\n" "public static Builder newBuilder($classname$ prototype) {\n" - " return newBuilder().mergeFrom(prototype);\n" + " return defaultInstance.toBuilder().mergeFrom(prototype);\n" + "}\n" + "public Builder toBuilder() {\n" + " return this == defaultInstance\n" + " ? new Builder() : new Builder().mergeFrom(this);\n" "}\n" - "public Builder toBuilder() { return newBuilder(this); }\n" "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); @@ -800,7 +875,7 @@ void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { } printer->Indent(); - GenerateDescriptorMethods(printer); + GenerateDescriptorMethods(printer, true); GenerateCommonBuilderMethods(printer); if (HasGeneratedMethods(descriptor_)) { @@ -884,7 +959,7 @@ void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { } void ImmutableMessageGenerator:: -GenerateDescriptorMethods(io::Printer* printer) { +GenerateDescriptorMethods(io::Printer* printer, bool is_builder) { if (HasDescriptorMethods(descriptor_)) { if (!descriptor_->options().no_standard_descriptor_accessor()) { printer->Print( @@ -917,9 +992,9 @@ GenerateDescriptorMethods(io::Printer* printer) { const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); printer->Print( "case $number$:\n" - " return $name$_;\n", + " return internalGet$capitalized_name$();\n", "number", SimpleItoa(field->number()), - "name", info->name); + "capitalized_name", info->capitalized_name); } printer->Print( "default:\n" @@ -930,6 +1005,34 @@ GenerateDescriptorMethods(io::Printer* printer) { printer->Print( " }\n" "}\n"); + if (is_builder) { + printer->Print( + "@SuppressWarnings({\"rawtypes\"})\n" + "protected com.google.protobuf.MapField internalGetMutableMapField(\n" + " int number) {\n" + " switch (number) {\n"); + printer->Indent(); + printer->Indent(); + for (int i = 0; i < map_fields.size(); ++i) { + const FieldDescriptor* field = map_fields[i]; + const FieldGeneratorInfo* info = + context_->GetFieldGeneratorInfo(field); + printer->Print( + "case $number$:\n" + " return internalGetMutable$capitalized_name$();\n", + "number", SimpleItoa(field->number()), + "capitalized_name", info->capitalized_name); + } + printer->Print( + "default:\n" + " throw new RuntimeException(\n" + " \"Invalid map field number: \" + number);\n"); + printer->Outdent(); + printer->Outdent(); + printer->Print( + " }\n" + "}\n"); + } } printer->Print( "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" @@ -967,7 +1070,7 @@ GenerateCommonBuilderMethods(io::Printer* printer) { "classname", name_resolver_->GetImmutableClassName(descriptor_)); } else { // LITE runtime passes along the default instance to implement - // getDefaultInstanceForType() at the GneratedMessageLite level. + // getDefaultInstanceForType() at the GeneratedMessageLite level. printer->Print( "// Construct using $classname$.newBuilder()\n" "private Builder() {\n" @@ -1070,22 +1173,17 @@ GenerateCommonBuilderMethods(io::Printer* printer) { if (HasDescriptorMethods(descriptor_)) { printer->Print( "public $classname$ buildPartial() {\n" - " $classname$ result = new $classname$(this);\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + " $classname$ result = new $classname$(this);\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } else { // LITE_RUNTIME only provides a single message constructor. printer->Print( "public $classname$ buildPartial() {\n" - " $classname$ result = null;\n" - " try {\n" - " result = new $classname$(\n" - " com.google.protobuf.Internal\n" - " .EMPTY_CODED_INPUT_STREAM,\n" - " com.google.protobuf.ExtensionRegistryLite\n" - " .getEmptyRegistry());\n" - " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" - " throw new RuntimeException(e);\n" - " }\n" + " $classname$ result = new $classname$(\n" + " com.google.protobuf.Internal\n" + " .EMPTY_CODED_INPUT_STREAM,\n" + " com.google.protobuf.ExtensionRegistryLite\n" + " .getEmptyRegistry());\n" " result.unknownFields = this.unknownFields;\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); @@ -1279,6 +1377,12 @@ GenerateBuilderParsingMethods(io::Printer* printer) { void ImmutableMessageGenerator::GenerateIsInitialized( io::Printer* printer, UseMemoization useMemoization) { + // LITE_RUNTIME avoids generating isInitialized if it's not needed. + if (!HasDescriptorMethods(descriptor_) + && !HasRequiredFields(descriptor_)) { + return; + } + bool memoization = useMemoization == MEMOIZE; if (memoization) { // Memoizes whether the protocol buffer is fully initialized (has all @@ -1566,8 +1670,7 @@ GenerateParsingConstructor(io::Printer* printer) { printer->Print( "private $classname$(\n" " com.google.protobuf.CodedInputStream input,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n", + " com.google.protobuf.ExtensionRegistryLite extensionRegistry) {\n", "classname", descriptor_->name()); printer->Indent(); @@ -1703,10 +1806,11 @@ GenerateParsingConstructor(io::Printer* printer) { printer->Outdent(); printer->Print( "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" - " throw e.setUnfinishedMessage(this);\n" + " throw new RuntimeException(e.setUnfinishedMessage(this));\n" "} catch (java.io.IOException e) {\n" - " throw new com.google.protobuf.InvalidProtocolBufferException(\n" - " e.getMessage()).setUnfinishedMessage(this);\n" + " throw new RuntimeException(\n" + " new com.google.protobuf.InvalidProtocolBufferException(\n" + " e.getMessage()).setUnfinishedMessage(this));\n" "} finally {\n"); printer->Indent(); @@ -1755,8 +1859,19 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { " throws com.google.protobuf.InvalidProtocolBufferException {\n", "classname", descriptor_->name()); if (HasGeneratedMethods(descriptor_)) { + // The parsing constructor throws an InvalidProtocolBufferException via a + // RuntimeException to aid in method pruning. We unwrap it here. printer->Print( - " return new $classname$(input, extensionRegistry);\n", + " try {\n" + " return new $classname$(input, extensionRegistry);\n" + " } catch (RuntimeException e) {\n" + " if (e.getCause() instanceof\n" + " com.google.protobuf.InvalidProtocolBufferException) {\n" + " throw (com.google.protobuf.InvalidProtocolBufferException)\n" + " e.getCause();\n" + " }\n" + " throw e;\n" + " }\n", "classname", descriptor_->name()); } else { // When parsing constructor isn't generated, use builder to parse messages. @@ -1783,13 +1898,16 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { "};\n" "\n"); - printer->Print( - "@java.lang.Override\n" - "public com.google.protobuf.Parser<$classname$> getParserForType() {\n" - " return PARSER;\n" - "}\n" - "\n", - "classname", descriptor_->name()); + if (HasDescriptorMethods(descriptor_)) { + // LITE_RUNTIME implements this at the GeneratedMessageLite level. + printer->Print( + "@java.lang.Override\n" + "public com.google.protobuf.Parser<$classname$> getParserForType() {\n" + " return PARSER;\n" + "}\n" + "\n", + "classname", descriptor_->name()); + } } // =================================================================== diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h index 4c4c137a..58dd5f99 100644 --- a/src/google/protobuf/compiler/java/java_message.h +++ b/src/google/protobuf/compiler/java/java_message.h @@ -121,7 +121,7 @@ class ImmutableMessageGenerator : public MessageGenerator { void GenerateBuilder(io::Printer* printer); void GenerateCommonBuilderMethods(io::Printer* printer); - void GenerateDescriptorMethods(io::Printer* printer); + void GenerateDescriptorMethods(io::Printer* printer, bool is_builder); void GenerateBuilderParsingMethods(io::Printer* printer); void GenerateIsInitialized(io::Printer* printer, UseMemoization useMemoization); diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc index 538f1248..a2d12a38 100644 --- a/src/google/protobuf/compiler/java/java_message_field.cc +++ b/src/google/protobuf/compiler/java/java_message_field.cc @@ -718,6 +718,7 @@ GenerateBuilderMembers(io::Printer* printer) const { " $oneof_name$_ = null;\n" " }\n" " $set_oneof_case_message$;\n" + " $on_changed$;\n" " return $name$Builder_;\n" "}\n"); } diff --git a/src/google/protobuf/compiler/java/java_names.h b/src/google/protobuf/compiler/java/java_names.h new file mode 100644 index 00000000..0d614335 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_names.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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// Provides a mechanism for mapping a descriptor to the +// fully-qualified name of the corresponding Java class. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_NAMES_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_NAMES_H__ + +#include <string> + +namespace google { +namespace protobuf { + +class Descriptor; +class EnumDescriptor; +class FileDescriptor; +class ServiceDescriptor; + +namespace compiler { +namespace java { + +// Requires: +// descriptor != NULL +// +// Returns: +// The fully-qualified Java class name. +string ClassName(const Descriptor* descriptor); + +// Requires: +// descriptor != NULL +// +// Returns: +// The fully-qualified Java class name. +string ClassName(const EnumDescriptor* descriptor); + +// Requires: +// descriptor != NULL +// +// Returns: +// The fully-qualified Java class name. +string ClassName(const FileDescriptor* descriptor); + +// Requires: +// descriptor != NULL +// +// Returns: +// The fully-qualified Java class name. +string ClassName(const ServiceDescriptor* descriptor); + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_NAMES_H__ diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc index e331d7a4..48757c60 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field.cc @@ -772,6 +772,9 @@ GenerateParsingDoneCode(io::Printer* printer) const { void RepeatedImmutablePrimitiveFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { if (descriptor_->options().packed()) { + // We invoke getSerializedSize in writeTo for messages that have packed + // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods. + // That makes it safe to rely on the memoized size here. printer->Print(variables_, "if (get$capitalized_name$List().size() > 0) {\n" " output.writeRawVarint32($tag$);\n" diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc index 2e61ea8a..70177367 100644 --- a/src/google/protobuf/compiler/java/java_shared_code_generator.cc +++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc @@ -171,7 +171,7 @@ void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) { string classname = FileJavaPackage(file_->dependency(i)) + "." + name_resolver_->GetDescriptorClassName( file_->dependency(i)); - dependencies.push_back(make_pair(filename, classname)); + dependencies.push_back(std::make_pair(filename, classname)); } } diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc index 1c9302af..8aa5699c 100644 --- a/src/google/protobuf/compiler/java/java_string_field.cc +++ b/src/google/protobuf/compiler/java/java_string_field.cc @@ -667,7 +667,7 @@ GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, "String s = input.readStringRequireUtf8();\n" "$set_oneof_case_message$;\n" - "$oneof_name$_ = s;\n}\n"); + "$oneof_name$_ = s;\n"); } else if (!HasDescriptorMethods(descriptor_->file())) { // Lite runtime should attempt to reduce allocations by attempting to // construct the string directly from the input stream buffer. This avoids diff --git a/src/google/protobuf/compiler/javanano/javanano_enum.cc b/src/google/protobuf/compiler/javanano/javanano_enum.cc index f934b05f..c6e8dfe9 100644 --- a/src/google/protobuf/compiler/javanano/javanano_enum.cc +++ b/src/google/protobuf/compiler/javanano/javanano_enum.cc @@ -73,13 +73,45 @@ void EnumGenerator::Generate(io::Printer* printer) { "// enum $classname$\n", "classname", descriptor_->name()); + const string classname = RenameJavaKeywords(descriptor_->name()); + // Start of container interface + // If generating intdefs, we use the container interface as the intdef if + // present. Otherwise, we just make an empty @interface parallel to the + // constants. + bool use_intdef = params_.generate_intdefs(); bool use_shell_class = params_.java_enum_style(); - if (use_shell_class) { - printer->Print( - "public interface $classname$ {\n", - "classname", RenameJavaKeywords(descriptor_->name())); + if (use_intdef) { + // @IntDef annotation so tools can enforce correctness + // Annotations will be discarded by the compiler + printer->Print("@java.lang.annotation.Retention(" + "java.lang.annotation.RetentionPolicy.SOURCE)\n" + "@android.support.annotation.IntDef({\n"); printer->Indent(); + for (int i = 0; i < canonical_values_.size(); i++) { + const string constant_name = + RenameJavaKeywords(canonical_values_[i]->name()); + if (use_shell_class) { + printer->Print("$classname$.$name$,\n", + "classname", classname, + "name", constant_name); + } else { + printer->Print("$name$,\n", "name", constant_name); + } + } + printer->Outdent(); + printer->Print("})\n"); + } + if (use_shell_class || use_intdef) { + printer->Print( + "public $at_for_intdef$interface $classname$ {\n", + "classname", classname, + "at_for_intdef", use_intdef ? "@" : ""); + if (use_shell_class) { + printer->Indent(); + } else { + printer->Print("}\n\n"); + } } // Canonical values diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc index 8a59d323..7666db38 100644 --- a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc @@ -76,6 +76,10 @@ void SetEnumVariables(const Params& params, internal::WireFormatLite::MakeTag(descriptor->number(), internal::WireFormat::WireTypeForFieldType(descriptor->type()))); (*variables)["message_name"] = descriptor->containing_type()->name(); + const EnumDescriptor* enum_type = descriptor->enum_type(); + (*variables)["message_type_intdef"] = "@" + + ToJavaName(params, enum_type->name(), true, + enum_type->containing_type(), enum_type->file()); } void LoadEnumValues(const Params& params, @@ -116,8 +120,10 @@ EnumFieldGenerator::~EnumFieldGenerator() {} void EnumFieldGenerator:: GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { - printer->Print(variables_, - "public $type$ $name$;\n"); + if (params_.generate_intdefs()) { + printer->Print(variables_, "$message_type_intdef$\n"); + } + printer->Print(variables_, "public $type$ $name$;\n"); if (params_.generate_has()) { printer->Print(variables_, @@ -256,12 +262,22 @@ AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {} void AccessorEnumFieldGenerator:: GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { + printer->Print(variables_, "private int $name$_;\n"); + if (params_.generate_intdefs()) { + printer->Print(variables_, "$message_type_intdef$\n"); + } printer->Print(variables_, - "private int $name$_;\n" "public int get$capitalized_name$() {\n" " return $name$_;\n" "}\n" - "public $message_name$ set$capitalized_name$(int value) {\n" + "public $message_name$ set$capitalized_name$("); + if (params_.generate_intdefs()) { + printer->Print(variables_, + "\n" + " $message_type_intdef$ "); + } + printer->Print(variables_, + "int value) {\n" " $name$_ = value;\n" " $set_has$;\n" " return this;\n" @@ -499,6 +515,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const { } void RepeatedEnumFieldGenerator:: +GenerateFixClonedCode(io::Printer* printer) const { + printer->Print(variables_, + "if (this.$name$ != null && this.$name$.length > 0) {\n" + " cloned.$name$ = this.$name$.clone();\n" + "}\n"); +} + +void RepeatedEnumFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { printer->Print(variables_, "if (!com.google.protobuf.nano.InternalNano.equals(\n" diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.h b/src/google/protobuf/compiler/javanano/javanano_enum_field.h index 00adc61f..b94790d6 100644 --- a/src/google/protobuf/compiler/javanano/javanano_enum_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.h @@ -106,6 +106,7 @@ class RepeatedEnumFieldGenerator : public FieldGenerator { void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCodeCode(io::Printer* printer) const; + void GenerateFixClonedCode(io::Printer* printer) const; private: void GenerateRepeatedDataSizeCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/javanano/javanano_extension.cc b/src/google/protobuf/compiler/javanano/javanano_extension.cc index 754ed550..0b9d1d8d 100644 --- a/src/google/protobuf/compiler/javanano/javanano_extension.cc +++ b/src/google/protobuf/compiler/javanano/javanano_extension.cc @@ -140,7 +140,7 @@ void ExtensionGenerator::Generate(io::Printer* printer) const { " com.google.protobuf.nano.Extension.create$repeated$$ext_type$(\n" " com.google.protobuf.nano.Extension.$type$,\n" " $class$.class,\n" - " $tag_params$);\n"); + " $tag_params$L);\n"); } } // namespace javanano diff --git a/src/google/protobuf/compiler/javanano/javanano_field.cc b/src/google/protobuf/compiler/javanano/javanano_field.cc index e3e4cefe..85257f3f 100644 --- a/src/google/protobuf/compiler/javanano/javanano_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_field.cc @@ -36,6 +36,7 @@ #include <google/protobuf/compiler/javanano/javanano_helpers.h> #include <google/protobuf/compiler/javanano/javanano_primitive_field.h> #include <google/protobuf/compiler/javanano/javanano_enum_field.h> +#include <google/protobuf/compiler/javanano/javanano_map_field.h> #include <google/protobuf/compiler/javanano/javanano_message_field.h> #include <google/protobuf/stubs/common.h> @@ -97,12 +98,24 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, if (field->is_repeated()) { switch (java_type) { case JAVATYPE_MESSAGE: - return new RepeatedMessageFieldGenerator(field, params); + if (IsMapEntry(field->message_type())) { + return new MapFieldGenerator(field, params); + } else { + return new RepeatedMessageFieldGenerator(field, params); + } case JAVATYPE_ENUM: return new RepeatedEnumFieldGenerator(field, params); default: return new RepeatedPrimitiveFieldGenerator(field, params); } + } else if (field->containing_oneof()) { + switch (java_type) { + case JAVATYPE_MESSAGE: + return new MessageOneofFieldGenerator(field, params); + case JAVATYPE_ENUM: + default: + return new PrimitiveOneofFieldGenerator(field, params); + } } else if (params.optional_field_accessors() && field->is_optional() && java_type != JAVATYPE_MESSAGE) { // We need a has-bit for each primitive/enum field because their default @@ -137,6 +150,59 @@ const FieldGenerator& FieldGeneratorMap::get( return *field_generators_[field->index()]; } +void SetCommonOneofVariables(const FieldDescriptor* descriptor, + map<string, string>* variables) { + (*variables)["oneof_name"] = + UnderscoresToCamelCase(descriptor->containing_oneof()); + (*variables)["oneof_capitalized_name"] = + UnderscoresToCapitalizedCamelCase(descriptor->containing_oneof()); + (*variables)["oneof_index"] = + SimpleItoa(descriptor->containing_oneof()->index()); + (*variables)["set_oneof_case"] = + "this." + (*variables)["oneof_name"] + + "Case_ = " + SimpleItoa(descriptor->number()); + (*variables)["clear_oneof_case"] = + "this." + (*variables)["oneof_name"] + "Case_ = 0"; + (*variables)["has_oneof_case"] = + "this." + (*variables)["oneof_name"] + "Case_ == " + + SimpleItoa(descriptor->number()); +} + +void GenerateOneofFieldEquals(const FieldDescriptor* descriptor, + const map<string, string>& variables, + io::Printer* printer) { + if (GetJavaType(descriptor) == JAVATYPE_BYTES) { + printer->Print(variables, + "if (this.has$capitalized_name$()) {\n" + " if (!java.util.Arrays.equals((byte[]) this.$oneof_name$_,\n" + " (byte[]) other.$oneof_name$_)) {\n" + " return false;\n" + " }\n" + "}\n"); + } else { + printer->Print(variables, + "if (this.has$capitalized_name$()) {\n" + " if (!this.$oneof_name$_.equals(other.$oneof_name$_)) {\n" + " return false;\n" + " }\n" + "}\n"); + } +} + +void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor, + const map<string, string>& variables, + io::Printer* printer) { + if (GetJavaType(descriptor) == JAVATYPE_BYTES) { + printer->Print(variables, + "result = 31 * result + ($has_oneof_case$\n" + " ? java.util.Arrays.hashCode((byte[]) this.$oneof_name$_) : 0);\n"); + } else { + printer->Print(variables, + "result = 31 * result +\n" + " ($has_oneof_case$ ? this.$oneof_name$_.hashCode() : 0);\n"); + } +} + } // namespace javanano } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/javanano/javanano_field.h b/src/google/protobuf/compiler/javanano/javanano_field.h index 6170c2c0..57c221f4 100644 --- a/src/google/protobuf/compiler/javanano/javanano_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_field.h @@ -35,6 +35,7 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__ +#include <map> #include <string> #include <google/protobuf/stubs/common.h> #include <google/protobuf/descriptor.h> @@ -82,6 +83,7 @@ class FieldGenerator { virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; virtual void GenerateEqualsCode(io::Printer* printer) const = 0; virtual void GenerateHashCodeCode(io::Printer* printer) const = 0; + virtual void GenerateFixClonedCode(io::Printer* printer) const {} protected: const Params& params_; @@ -111,6 +113,15 @@ class FieldGeneratorMap { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); }; +void SetCommonOneofVariables(const FieldDescriptor* descriptor, + map<string, string>* variables); +void GenerateOneofFieldEquals(const FieldDescriptor* descriptor, + const map<string, string>& variables, + io::Printer* printer); +void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor, + const map<string, string>& variables, + io::Printer* printer); + } // namespace javanano } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc index b5fbcd5f..ad215cb7 100644 --- a/src/google/protobuf/compiler/javanano/javanano_generator.cc +++ b/src/google/protobuf/compiler/javanano/javanano_generator.cc @@ -152,6 +152,12 @@ bool JavaNanoGenerator::Generate(const FileDescriptor* file, params.set_ignore_services(option_value == "true"); } else if (option_name == "parcelable_messages") { params.set_parcelable_messages(option_value == "true"); + } else if (option_name == "generate_clone") { + params.set_generate_clone(option_value == "true"); + } else if (option_name == "generate_intdefs") { + params.set_generate_intdefs(option_value == "true"); + } else if (option_name == "generate_clear") { + params.set_generate_clear(option_value == "true"); } else { *error = "Ignore unknown javanano generator option: " + option_name; } diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc index 2149418a..0d2ae9db 100644 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc +++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc @@ -154,6 +154,14 @@ string UnderscoresToCamelCase(const MethodDescriptor* method) { return UnderscoresToCamelCaseImpl(method->name(), false); } +string UnderscoresToCamelCase(const OneofDescriptor* oneof) { + return UnderscoresToCamelCaseImpl(oneof->name(), false); +} + +string UnderscoresToCapitalizedCamelCase(const OneofDescriptor* oneof) { + return UnderscoresToCamelCaseImpl(oneof->name(), true); +} + string RenameJavaKeywords(const string& input) { return sRenameKeywords.RenameJavaKeywordsImpl(input); } @@ -560,6 +568,17 @@ void SetBitOperationVariables(const string name, (*variables)["different_" + name] = GenerateDifferentBit(bitIndex); } +bool HasMapField(const Descriptor* descriptor) { + for (int i = 0; i < descriptor->field_count(); ++i) { + const FieldDescriptor* field = descriptor->field(i); + if (field->type() == FieldDescriptor::TYPE_MESSAGE && + IsMapEntry(field->message_type())) { + return true; + } + } + return false; +} + } // namespace javanano } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.h b/src/google/protobuf/compiler/javanano/javanano_helpers.h index 29310743..014c85ae 100644 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.h +++ b/src/google/protobuf/compiler/javanano/javanano_helpers.h @@ -54,7 +54,9 @@ extern const char kThinSeparator[]; // Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes // "fooBarBaz" or "FooBarBaz", respectively. string UnderscoresToCamelCase(const FieldDescriptor* field); +string UnderscoresToCamelCase(const OneofDescriptor* oneof); string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field); +string UnderscoresToCapitalizedCamelCase(const OneofDescriptor* oneof); // Appends an "_" to the end of a field where the name is a reserved java // keyword. For example int32 public = 1 will generate int public_. @@ -181,6 +183,14 @@ string GenerateDifferentBit(int bit_index); void SetBitOperationVariables(const string name, int bitIndex, map<string, string>* variables); +inline bool IsMapEntry(const Descriptor* descriptor) { + // TODO(liujisi): Add an option to turn on maps for proto2 syntax as well. + return descriptor->options().map_entry() && + descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3; +} + +bool HasMapField(const Descriptor* descriptor); + } // namespace javanano } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.cc b/src/google/protobuf/compiler/javanano/javanano_map_field.cc new file mode 100644 index 00000000..83b2b0ce --- /dev/null +++ b/src/google/protobuf/compiler/javanano/javanano_map_field.cc @@ -0,0 +1,186 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <google/protobuf/compiler/javanano/javanano_map_field.h> +#include <google/protobuf/compiler/javanano/javanano_helpers.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/wire_format.h> +#include <google/protobuf/stubs/strutil.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace javanano { + +namespace { + +string TypeName(const Params& params, const FieldDescriptor* field, + bool boxed) { + JavaType java_type = GetJavaType(field); + switch (java_type) { + case JAVATYPE_MESSAGE: + return ClassName(params, field->message_type()); + case JAVATYPE_INT: + case JAVATYPE_LONG: + case JAVATYPE_FLOAT: + case JAVATYPE_DOUBLE: + case JAVATYPE_BOOLEAN: + case JAVATYPE_STRING: + case JAVATYPE_BYTES: + case JAVATYPE_ENUM: + if (boxed) { + return BoxedPrimitiveTypeName(java_type); + } else { + return PrimitiveTypeName(java_type); + } + // No default because we want the compiler to complain if any new JavaTypes + // are added.. + } + + GOOGLE_LOG(FATAL) << "should not reach here."; + return ""; +} + +const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) { + GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type()); + const Descriptor* message = descriptor->message_type(); + GOOGLE_CHECK(message->options().map_entry()); + return message->FindFieldByName("key"); +} + +const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) { + GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type()); + const Descriptor* message = descriptor->message_type(); + GOOGLE_CHECK(message->options().map_entry()); + return message->FindFieldByName("value"); +} + +void SetMapVariables(const Params& params, + const FieldDescriptor* descriptor, map<string, string>* variables) { + const FieldDescriptor* key = KeyField(descriptor); + const FieldDescriptor* value = ValueField(descriptor); + (*variables)["name"] = + RenameJavaKeywords(UnderscoresToCamelCase(descriptor)); + (*variables)["number"] = SimpleItoa(descriptor->number()); + (*variables)["key_type"] = TypeName(params, key, false); + (*variables)["boxed_key_type"] = TypeName(params,key, true); + (*variables)["key_desc_type"] = + "TYPE_" + ToUpper(FieldDescriptor::TypeName(key->type())); + (*variables)["key_tag"] = SimpleItoa(internal::WireFormat::MakeTag(key)); + (*variables)["value_type"] = TypeName(params, value, false); + (*variables)["boxed_value_type"] = TypeName(params, value, true); + (*variables)["value_desc_type"] = + "TYPE_" + ToUpper(FieldDescriptor::TypeName(value->type())); + (*variables)["value_tag"] = SimpleItoa(internal::WireFormat::MakeTag(value)); + (*variables)["type_parameters"] = + (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"]; + (*variables)["value_default"] = + value->type() == FieldDescriptor::TYPE_MESSAGE + ? "new " + (*variables)["value_type"] + "()" + : "null"; +} +} // namespace + +// =================================================================== +MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, + const Params& params) + : FieldGenerator(params), descriptor_(descriptor) { + SetMapVariables(params, descriptor, &variables_); +} + +MapFieldGenerator::~MapFieldGenerator() {} + +void MapFieldGenerator:: +GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { + printer->Print(variables_, + "public java.util.Map<$type_parameters$> $name$;\n"); +} + +void MapFieldGenerator:: +GenerateClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$ = null;\n"); +} + +void MapFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "this.$name$ = com.google.protobuf.nano.InternalNano.mergeMapEntry(\n" + " input, this.$name$, mapFactory,\n" + " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n" + " com.google.protobuf.nano.InternalNano.$value_desc_type$,\n" + " $value_default$,\n" + " $key_tag$, $value_tag$);\n" + "\n"); +} + +void MapFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if (this.$name$ != null) {\n" + " com.google.protobuf.nano.InternalNano.serializeMapField(\n" + " output, this.$name$, $number$,\n" + " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n" + " com.google.protobuf.nano.InternalNano.$value_desc_type$);\n" + "}\n"); +} + +void MapFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if (this.$name$ != null) {\n" + " size += com.google.protobuf.nano.InternalNano.computeMapFieldSize(\n" + " this.$name$, $number$,\n" + " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n" + " com.google.protobuf.nano.InternalNano.$value_desc_type$);\n" + "}\n"); +} + +void MapFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "if (!com.google.protobuf.nano.InternalNano.equals(\n" + " this.$name$, other.$name$)) {\n" + " return false;\n" + "}\n"); +} + +void MapFieldGenerator:: +GenerateHashCodeCode(io::Printer* printer) const { + printer->Print(variables_, + "result = 31 * result +\n" + " com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n"); +} + +} // namespace javanano +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.h b/src/google/protobuf/compiler/javanano/javanano_map_field.h new file mode 100644 index 00000000..c01bde38 --- /dev/null +++ b/src/google/protobuf/compiler/javanano/javanano_map_field.h @@ -0,0 +1,70 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__ + +#include <map> +#include <string> +#include <vector> +#include <google/protobuf/compiler/javanano/javanano_field.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace javanano { + +class MapFieldGenerator : public FieldGenerator { + public: + explicit MapFieldGenerator( + const FieldDescriptor* descriptor, const Params& params); + ~MapFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GenerateMembers(io::Printer* printer, bool lazy_init) const; + void GenerateClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCodeCode(io::Printer* printer) const; + + private: + const FieldDescriptor* descriptor_; + map<string, string> variables_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator); +}; + +} // namespace javanano +} // namespace compiler +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__ diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc index 7c52ca31..a41da5ae 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message.cc @@ -90,6 +90,7 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { // Generate static members for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { // TODO(kenton): Reuse MessageGenerator objects? + if (IsMapEntry(descriptor_->nested_type(i))) continue; MessageGenerator(descriptor_->nested_type(i), params_) .GenerateStaticVariables(printer); } @@ -100,6 +101,7 @@ void MessageGenerator::GenerateStaticVariableInitializers( // Generate static member initializers for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { // TODO(kenton): Reuse MessageGenerator objects? + if (IsMapEntry(descriptor_->nested_type(i))) continue; MessageGenerator(descriptor_->nested_type(i), params_) .GenerateStaticVariableInitializers(printer); } @@ -134,21 +136,37 @@ void MessageGenerator::Generate(io::Printer* printer) { } if (params_.store_unknown_fields() && params_.parcelable_messages()) { printer->Print( - " com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$> {\n", + " com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$>", "classname", descriptor_->name()); } else if (params_.store_unknown_fields()) { printer->Print( - " com.google.protobuf.nano.ExtendableMessageNano<$classname$> {\n", + " com.google.protobuf.nano.ExtendableMessageNano<$classname$>", "classname", descriptor_->name()); } else if (params_.parcelable_messages()) { printer->Print( - " com.google.protobuf.nano.android.ParcelableMessageNano {\n"); + " com.google.protobuf.nano.android.ParcelableMessageNano"); } else { printer->Print( - " com.google.protobuf.nano.MessageNano {\n"); + " com.google.protobuf.nano.MessageNano"); + } + if (params_.generate_clone()) { + printer->Print(" implements java.lang.Cloneable {\n"); + } else { + printer->Print(" {\n"); } printer->Indent(); + if (params_.parcelable_messages()) { + printer->Print( + "\n" + "// Used by Parcelable\n" + "@SuppressWarnings({\"unused\"})\n" + "public static final android.os.Parcelable.Creator<$classname$> CREATOR =\n" + " new com.google.protobuf.nano.android.ParcelableMessageNanoCreator<\n" + " $classname$>($classname$.class);\n", + "classname", descriptor_->name()); + } + // Nested types and extensions for (int i = 0; i < descriptor_->extension_count(); i++) { ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer); @@ -159,9 +177,44 @@ void MessageGenerator::Generate(io::Printer* printer) { } for (int i = 0; i < descriptor_->nested_type_count(); i++) { + if (IsMapEntry(descriptor_->nested_type(i))) continue; MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer); } + // oneof + map<string, string> vars; + vars["message_name"] = descriptor_->name(); + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i); + vars["oneof_name"] = UnderscoresToCamelCase(oneof_desc); + vars["oneof_capitalized_name"] = + UnderscoresToCapitalizedCamelCase(oneof_desc); + vars["oneof_index"] = SimpleItoa(oneof_desc->index()); + // Oneof Constants + for (int j = 0; j < oneof_desc->field_count(); j++) { + const FieldDescriptor* field = oneof_desc->field(j); + vars["number"] = SimpleItoa(field->number()); + vars["cap_field_name"] = ToUpper(field->name()); + printer->Print(vars, + "public static final int $cap_field_name$_FIELD_NUMBER = $number$;\n"); + } + // oneofCase_ and oneof_ + printer->Print(vars, + "private int $oneof_name$Case_ = 0;\n" + "private java.lang.Object $oneof_name$_;\n"); + printer->Print(vars, + "public int get$oneof_capitalized_name$Case() {\n" + " return this.$oneof_name$Case_;\n" + "}\n"); + // Oneof clear + printer->Print(vars, + "public $message_name$ clear$oneof_capitalized_name$() {\n" + " this.$oneof_name$Case_ = 0;\n" + " this.$oneof_name$_ = null;\n" + " return this;\n" + "}\n"); + } + // Lazy initialization of otherwise static final fields can help prevent the // class initializer from being generated. We want to prevent it because it // stops ProGuard from inlining any methods in this class into call sites and @@ -251,20 +304,28 @@ void MessageGenerator::Generate(io::Printer* printer) { } printer->Print("}\n"); } else { + printer->Print( + "\n" + "public $classname$() {\n", + "classname", descriptor_->name()); if (params_.generate_clear()) { - printer->Print( - "\n" - "public $classname$() {\n" - " clear();\n" - "}\n", - "classname", descriptor_->name()); + printer->Print(" clear();\n"); + } else { + printer->Indent(); + GenerateFieldInitializers(printer); + printer->Outdent(); } + printer->Print("}\n"); } // Other methods in this class GenerateClear(printer); + if (params_.generate_clone()) { + GenerateClone(printer); + } + if (params_.generate_equals()) { GenerateEquals(printer); GenerateHashCode(printer); @@ -342,6 +403,11 @@ void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) { "classname", descriptor_->name()); printer->Indent(); + if (HasMapField(descriptor_)) { + printer->Print( + "com.google.protobuf.nano.MapFactories.MapFactory mapFactory =\n" + " com.google.protobuf.nano.MapFactories.getMapFactory();\n"); + } printer->Print( "while (true) {\n"); @@ -453,6 +519,15 @@ void MessageGenerator::GenerateClear(io::Printer* printer) { "classname", descriptor_->name()); printer->Indent(); + GenerateFieldInitializers(printer); + + printer->Outdent(); + printer->Print( + " return this;\n" + "}\n"); +} + +void MessageGenerator::GenerateFieldInitializers(io::Printer* printer) { // Clear bit fields. int totalInts = (field_generators_.total_bits() + 31) / 32; for (int i = 0; i < totalInts; i++) { @@ -466,16 +541,46 @@ void MessageGenerator::GenerateClear(io::Printer* printer) { field_generators_.get(field).GenerateClearCode(printer); } + // Clear oneofs. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "clear$oneof_capitalized_name$();\n", + "oneof_capitalized_name", UnderscoresToCapitalizedCamelCase( + descriptor_->oneof_decl(i))); + } + // Clear unknown fields. if (params_.store_unknown_fields()) { printer->Print("unknownFieldData = null;\n"); } + printer->Print("cachedSize = -1;\n"); +} + +void MessageGenerator::GenerateClone(io::Printer* printer) { + printer->Print( + "@Override\n" + "public $classname$ clone() {\n", + "classname", descriptor_->name()); + printer->Indent(); + + printer->Print( + "$classname$ cloned;\n" + "try {\n" + " cloned = ($classname$) super.clone();\n" + "} catch (java.lang.CloneNotSupportedException e) {\n" + " throw new java.lang.AssertionError(e);\n" + "}\n", + "classname", descriptor_->name()); + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)).GenerateFixClonedCode(printer); + } printer->Outdent(); printer->Print( - " cachedSize = -1;\n" - " return this;\n" - "}\n"); + " return cloned;\n" + "}\n" + "\n"); } void MessageGenerator::GenerateEquals(io::Printer* printer) { @@ -501,6 +606,16 @@ void MessageGenerator::GenerateEquals(io::Printer* printer) { "$classname$ other = ($classname$) o;\n", "classname", descriptor_->name()); + // Checking oneof case before checking each oneof field. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i); + printer->Print( + "if (this.$oneof_name$Case_ != other.$oneof_name$Case_) {\n" + " return false;\n" + "}\n", + "oneof_name", UnderscoresToCamelCase(oneof_desc)); + } + for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); field_generators_.get(field).GenerateEqualsCode(printer); @@ -508,7 +623,11 @@ void MessageGenerator::GenerateEquals(io::Printer* printer) { if (params_.store_unknown_fields()) { printer->Print( - "return unknownFieldDataEquals(other);\n"); + "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n" + " return other.unknownFieldData == null || other.unknownFieldData.isEmpty();\n" + "} else {\n" + " return unknownFieldData.equals(other.unknownFieldData);\n" + "}"); } else { printer->Print( "return true;\n"); @@ -538,7 +657,9 @@ void MessageGenerator::GenerateHashCode(io::Printer* printer) { if (params_.store_unknown_fields()) { printer->Print( - "result = 31 * result + unknownFieldDataHashCode();\n"); + "result = 31 * result + \n" + " (unknownFieldData == null || unknownFieldData.isEmpty() ? 0 : \n" + " unknownFieldData.hashCode());\n"); } printer->Print("return result;\n"); diff --git a/src/google/protobuf/compiler/javanano/javanano_message.h b/src/google/protobuf/compiler/javanano/javanano_message.h index 6f25a3a0..281ec64f 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.h +++ b/src/google/protobuf/compiler/javanano/javanano_message.h @@ -77,8 +77,10 @@ class MessageGenerator { const FieldDescriptor* field); void GenerateClear(io::Printer* printer); + void GenerateFieldInitializers(io::Printer* printer); void GenerateEquals(io::Printer* printer); void GenerateHashCode(io::Printer* printer); + void GenerateClone(io::Printer* printer); const Params& params_; const Descriptor* descriptor_; diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc index a46081d0..d1d04b52 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message_field.cc @@ -127,6 +127,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const { } void MessageFieldGenerator:: +GenerateFixClonedCode(io::Printer* printer) const { + printer->Print(variables_, + "if (this.$name$ != null) {\n" + " cloned.$name$ = this.$name$.clone();\n" + "}\n"); +} + +void MessageFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { printer->Print(variables_, "if (this.$name$ == null) { \n" @@ -146,12 +154,95 @@ GenerateHashCodeCode(io::Printer* printer) const { "result = 31 * result +\n" " (this.$name$ == null ? 0 : this.$name$.hashCode());\n"); } +// =================================================================== + +MessageOneofFieldGenerator::MessageOneofFieldGenerator( + const FieldDescriptor* descriptor, const Params& params) + : FieldGenerator(params), descriptor_(descriptor) { + SetMessageVariables(params, descriptor, &variables_); + SetCommonOneofVariables(descriptor, &variables_); +} + +MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {} + +void MessageOneofFieldGenerator:: +GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { + printer->Print(variables_, + "public boolean has$capitalized_name$() {\n" + " return $has_oneof_case$;\n" + "}\n" + "public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case$) {\n" + " return ($type$) this.$oneof_name$_;\n" + " }\n" + " return null;\n" + "}\n" + "public $message_name$ set$capitalized_name$($type$ value) {\n" + " if (value == null) { throw new java.lang.NullPointerException(); }\n" + " $set_oneof_case$;\n" + " this.$oneof_name$_ = value;\n" + " return this;\n" + "}\n"); +} + +void MessageOneofFieldGenerator:: +GenerateClearCode(io::Printer* printer) const { + // No clear method for oneof fields. +} + +void MessageOneofFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (!($has_oneof_case$)) {\n" + " this.$oneof_name$_ = new $type$();\n" + "}\n" + "input.readMessage(\n" + " (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n" + "$set_oneof_case$;\n"); +} + +void MessageOneofFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case$) {\n" + " output.writeMessage($number$,\n" + " (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n" + "}\n"); +} + +void MessageOneofFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case$) {\n" + " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" + " .computeMessageSize($number$,\n" + " (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n" + "}\n"); +} + +void MessageOneofFieldGenerator:: +GenerateFixClonedCode(io::Printer* printer) const { + printer->Print(variables_, + "if (this.$oneof_name$ != null) {\n" + " cloned.$oneof_name$ = this.$oneof_name$.clone();\n" + "}\n"); +} + +void MessageOneofFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + GenerateOneofFieldEquals(descriptor_, variables_, printer); +} + +void MessageOneofFieldGenerator:: +GenerateHashCodeCode(io::Printer* printer) const { + GenerateOneofFieldHashCode(descriptor_, variables_, printer); +} // =================================================================== -RepeatedMessageFieldGenerator:: -RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params) - : FieldGenerator(params), descriptor_(descriptor) { +RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( + const FieldDescriptor* descriptor, const Params& params) + : FieldGenerator(params), descriptor_(descriptor) { SetMessageVariables(params, descriptor, &variables_); } @@ -238,6 +329,19 @@ GenerateSerializedSizeCode(io::Printer* printer) const { } void RepeatedMessageFieldGenerator:: +GenerateFixClonedCode(io::Printer* printer) const { + printer->Print(variables_, + "if (this.$name$ != null && this.$name$.length > 0) {\n" + " cloned.$name$ = new $type$[this.$name$.length];\n" + " for (int i = 0; i < this.$name$.length; i++) {\n" + " if (this.$name$[i] != null) {\n" + " cloned.$name$[i] = this.$name$[i].clone();\n" + " }\n" + " }\n" + "}\n"); +} + +void RepeatedMessageFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { printer->Print(variables_, "if (!com.google.protobuf.nano.InternalNano.equals(\n" diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.h b/src/google/protobuf/compiler/javanano/javanano_message_field.h index 5d35fd24..e074735c 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_message_field.h @@ -58,6 +58,7 @@ class MessageFieldGenerator : public FieldGenerator { void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCodeCode(io::Printer* printer) const; + void GenerateFixClonedCode(io::Printer* printer) const; private: const FieldDescriptor* descriptor_; @@ -66,6 +67,29 @@ class MessageFieldGenerator : public FieldGenerator { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); }; +class MessageOneofFieldGenerator : public FieldGenerator { + public: + explicit MessageOneofFieldGenerator(const FieldDescriptor* descriptor, + const Params& params); + ~MessageOneofFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GenerateMembers(io::Printer* printer, bool lazy_init) const; + void GenerateClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCodeCode(io::Printer* printer) const; + void GenerateFixClonedCode(io::Printer* printer) const; + + private: + const FieldDescriptor* descriptor_; + map<string, string> variables_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator); +}; + class RepeatedMessageFieldGenerator : public FieldGenerator { public: explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, @@ -80,6 +104,7 @@ class RepeatedMessageFieldGenerator : public FieldGenerator { void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCodeCode(io::Printer* printer) const; + void GenerateFixClonedCode(io::Printer* printer) const; private: const FieldDescriptor* descriptor_; diff --git a/src/google/protobuf/compiler/javanano/javanano_params.h b/src/google/protobuf/compiler/javanano/javanano_params.h index 4691f360..e3b4bb93 100644 --- a/src/google/protobuf/compiler/javanano/javanano_params.h +++ b/src/google/protobuf/compiler/javanano/javanano_params.h @@ -66,6 +66,8 @@ class Params { bool parcelable_messages_; bool reftypes_primitive_enums_; bool generate_clear_; + bool generate_clone_; + bool generate_intdefs_; public: Params(const string & base_name) : @@ -81,7 +83,9 @@ class Params { ignore_services_(false), parcelable_messages_(false), reftypes_primitive_enums_(false), - generate_clear_(true) { + generate_clear_(true), + generate_clone_(false), + generate_intdefs_(false) { } const string& base_name() const { @@ -231,6 +235,20 @@ class Params { bool generate_clear() const { return generate_clear_; } + + void set_generate_clone(bool value) { + generate_clone_ = value; + } + bool generate_clone() const { + return generate_clone_; + } + + void set_generate_intdefs(bool value) { + generate_intdefs_ = value; + } + bool generate_intdefs() const { + return generate_intdefs_; + } }; } // namespace javanano diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc index a3bc3a84..978abf2c 100644 --- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc @@ -155,28 +155,6 @@ int FixedSize(FieldDescriptor::Type type) { return -1; } -// Return true if the type is a that has variable length -// for instance String's. -bool IsVariableLenType(JavaType type) { - switch (type) { - case JAVATYPE_INT : return false; - case JAVATYPE_LONG : return false; - case JAVATYPE_FLOAT : return false; - case JAVATYPE_DOUBLE : return false; - case JAVATYPE_BOOLEAN: return false; - case JAVATYPE_STRING : return true; - case JAVATYPE_BYTES : return true; - case JAVATYPE_ENUM : return false; - case JAVATYPE_MESSAGE: return true; - - // No default because we want the compiler to complain if any new - // JavaTypes are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return false; -} - bool AllAscii(const string& text) { for (int i = 0; i < text.size(); i++) { if ((text[i] & 0x80) != 0) { @@ -186,6 +164,7 @@ bool AllAscii(const string& text) { return true; } + void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params, map<string, string>* variables) { (*variables)["name"] = @@ -385,6 +364,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const { } } +void RepeatedPrimitiveFieldGenerator:: +GenerateFixClonedCode(io::Printer* printer) const { + printer->Print(variables_, + "if (this.$name$ != null && this.$name$.length > 0) {\n" + " cloned.$name$ = this.$name$.clone();\n" + "}\n"); +} + void PrimitiveFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { // We define equality as serialized form equality. If generate_has(), @@ -706,8 +693,79 @@ GenerateHashCodeCode(io::Printer* printer) const { // =================================================================== -RepeatedPrimitiveFieldGenerator:: -RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params) +PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator( + const FieldDescriptor* descriptor, const Params& params) + : FieldGenerator(params), descriptor_(descriptor) { + SetPrimitiveVariables(descriptor, params, &variables_); + SetCommonOneofVariables(descriptor, &variables_); +} + +PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {} + +void PrimitiveOneofFieldGenerator::GenerateMembers( + io::Printer* printer, bool /*unused lazy_init*/) const { + printer->Print(variables_, + "public boolean has$capitalized_name$() {\n" + " return $has_oneof_case$;\n" + "}\n" + "public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case$) {\n" + " return ($type$) ($boxed_type$) this.$oneof_name$_;\n" + " }\n" + " return $default$;\n" + "}\n" + "public $message_name$ set$capitalized_name$($type$ value) {\n" + " $set_oneof_case$;\n" + " this.$oneof_name$_ = value;\n" + " return this;\n" + "}\n"); +} + +void PrimitiveOneofFieldGenerator::GenerateClearCode( + io::Printer* printer) const { + // No clear method for oneof fields. +} + +void PrimitiveOneofFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { + printer->Print(variables_, + "this.$oneof_name$_ = input.read$capitalized_type$();\n" + "$set_oneof_case$;\n"); +} + +void PrimitiveOneofFieldGenerator::GenerateSerializationCode( + io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case$) {\n" + " output.write$capitalized_type$(\n" + " $number$, ($boxed_type$) this.$oneof_name$_);\n" + "}\n"); +} + +void PrimitiveOneofFieldGenerator::GenerateSerializedSizeCode( + io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case$) {\n" + " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" + " .compute$capitalized_type$Size(\n" + " $number$, ($boxed_type$) this.$oneof_name$_);\n" + "}\n"); +} + +void PrimitiveOneofFieldGenerator::GenerateEqualsCode( + io::Printer* printer) const { + GenerateOneofFieldEquals(descriptor_, variables_, printer); +} + +void PrimitiveOneofFieldGenerator::GenerateHashCodeCode( + io::Printer* printer) const { + GenerateOneofFieldHashCode(descriptor_, variables_, printer); +} + +// =================================================================== + +RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( + const FieldDescriptor* descriptor, const Params& params) : FieldGenerator(params), descriptor_(descriptor) { SetPrimitiveVariables(descriptor, params, &variables_); } diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h index c04a19b7..a01981dd 100644 --- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h @@ -47,7 +47,7 @@ namespace javanano { class PrimitiveFieldGenerator : public FieldGenerator { public: explicit PrimitiveFieldGenerator( - const FieldDescriptor* descriptor, const Params ¶ms); + const FieldDescriptor* descriptor, const Params& params); ~PrimitiveFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -94,9 +94,32 @@ class AccessorPrimitiveFieldGenerator : public FieldGenerator { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorPrimitiveFieldGenerator); }; +class PrimitiveOneofFieldGenerator : public FieldGenerator { + public: + explicit PrimitiveOneofFieldGenerator( + const FieldDescriptor* descriptor, const Params& params); + ~PrimitiveOneofFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GenerateMembers(io::Printer* printer, bool lazy_init) const; + void GenerateClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCodeCode(io::Printer* printer) const; + + private: + const FieldDescriptor* descriptor_; + map<string, string> variables_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator); +}; + class RepeatedPrimitiveFieldGenerator : public FieldGenerator { public: - explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params); + explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, + const Params& params); ~RepeatedPrimitiveFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -108,6 +131,7 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator { void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCodeCode(io::Printer* printer) const; + void GenerateFixClonedCode(io::Printer* printer) const; private: void GenerateRepeatedDataSizeCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc index 2f5bdaf7..cff80164 100644 --- a/src/google/protobuf/compiler/main.cc +++ b/src/google/protobuf/compiler/main.cc @@ -34,7 +34,9 @@ #include <google/protobuf/compiler/cpp/cpp_generator.h> #include <google/protobuf/compiler/python/python_generator.h> #include <google/protobuf/compiler/java/java_generator.h> - +#include <google/protobuf/compiler/javanano/javanano_generator.h> +#include <google/protobuf/compiler/ruby/ruby_generator.h> +#include <google/protobuf/compiler/objectivec/objectivec_generator.h> int main(int argc, char* argv[]) { @@ -57,5 +59,20 @@ int main(int argc, char* argv[]) { cli.RegisterGenerator("--python_out", &py_generator, "Generate Python source file."); + // Java Nano + google::protobuf::compiler::javanano::JavaNanoGenerator javanano_generator; + cli.RegisterGenerator("--javanano_out", &javanano_generator, + "Generate Java Nano source file."); + + // Ruby + google::protobuf::compiler::ruby::Generator rb_generator; + cli.RegisterGenerator("--ruby_out", &rb_generator, + "Generate Ruby source file."); + + // Objective C + google::protobuf::compiler::objectivec::ObjectiveCGenerator objc_generator; + cli.RegisterGenerator("--objc_out", &objc_generator, + "Generate Objective C header and source."); + return cli.Run(argc, argv); } diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc index e7d5117e..98261431 100644 --- a/src/google/protobuf/compiler/mock_code_generator.cc +++ b/src/google/protobuf/compiler/mock_code_generator.cc @@ -133,10 +133,10 @@ bool MockCodeGenerator::Generate( *error = "Saw message type MockCodeGenerator_Error."; return false; } else if (command == "Exit") { - cerr << "Saw message type MockCodeGenerator_Exit." << endl; + std::cerr << "Saw message type MockCodeGenerator_Exit." << std::endl; exit(123); } else if (command == "Abort") { - cerr << "Saw message type MockCodeGenerator_Abort." << endl; + std::cerr << "Saw message type MockCodeGenerator_Abort." << std::endl; abort(); } else if (command == "HasSourceCodeInfo") { FileDescriptorProto file_descriptor_proto; @@ -144,8 +144,8 @@ bool MockCodeGenerator::Generate( bool has_source_code_info = file_descriptor_proto.has_source_code_info() && file_descriptor_proto.source_code_info().location_size() > 0; - cerr << "Saw message type MockCodeGenerator_HasSourceCodeInfo: " - << has_source_code_info << "." << endl; + std::cerr << "Saw message type MockCodeGenerator_HasSourceCodeInfo: " + << has_source_code_info << "." << std::endl; abort(); } else { GOOGLE_LOG(FATAL) << "Unknown MockCodeGenerator command: " << command; diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc new file mode 100644 index 00000000..b7c720d2 --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc @@ -0,0 +1,199 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <map> +#include <string> + +#include <google/protobuf/compiler/objectivec/objectivec_enum.h> +#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/stubs/strutil.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) + : descriptor_(descriptor), + name_(EnumName(descriptor_)) { + for (int i = 0; i < descriptor_->value_count(); i++) { + const EnumValueDescriptor* value = descriptor_->value(i); + const EnumValueDescriptor* canonical_value = + descriptor_->FindValueByNumber(value->number()); + + if (value == canonical_value) { + base_values_.push_back(value); + } + all_values_.push_back(value); + } +} + +EnumGenerator::~EnumGenerator() {} + +void EnumGenerator::GenerateHeader(io::Printer* printer) { + string enum_comments; + SourceLocation location; + if (descriptor_->GetSourceLocation(&location)) { + enum_comments = BuildCommentsString(location); + } else { + enum_comments = ""; + } + + printer->Print( + "#pragma mark - Enum $name$\n" + "\n", + "name", name_); + + printer->Print("$comments$typedef GPB_ENUM($name$) {\n", + "comments", enum_comments, + "name", name_); + printer->Indent(); + + if (HasPreservingUnknownEnumSemantics(descriptor_->file())) { + // Include the unknown value. + printer->Print( + "$name$_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,\n", + "name", name_); + } + + for (int i = 0; i < all_values_.size(); i++) { + SourceLocation location; + if (all_values_[i]->GetSourceLocation(&location)) { + string comments = BuildCommentsString(location).c_str(); + if (comments.length() > 0) { + if (i > 0) { + printer->Print("\n"); + } + printer->Print(comments.c_str()); + } + } + + printer->Print( + "$name$ = $value$,\n", + "name", EnumValueName(all_values_[i]), + "value", SimpleItoa(all_values_[i]->number())); + } + printer->Outdent(); + printer->Print( + "};\n" + "\n" + "GPBEnumDescriptor *$name$_EnumDescriptor(void);\n" + "\n" + "BOOL $name$_IsValidValue(int32_t value);\n" + "\n", + "name", name_); +} + +void EnumGenerator::GenerateSource(io::Printer* printer) { + printer->Print( + "#pragma mark - Enum $name$\n" + "\n", + "name", name_); + + printer->Print( + "GPBEnumDescriptor *$name$_EnumDescriptor(void) {\n" + " static GPBEnumDescriptor *descriptor = NULL;\n" + " if (!descriptor) {\n" + " static GPBMessageEnumValueDescription values[] = {\n", + "name", name_); + printer->Indent(); + printer->Indent(); + printer->Indent(); + + // Note: For the TextFormat decode info, we can't use the enum value as + // the key because protocol buffer enums have 'allow_alias', which lets + // a value be used more than once. Instead, the index into the list of + // enum value descriptions is used. Note: start with -1 so the first one + // will be zero. + TextFormatDecodeData text_format_decode_data; + int enum_value_description_key = -1; + + for (int i = 0; i < all_values_.size(); i++) { + ++enum_value_description_key; + string short_name(EnumValueShortName(all_values_[i])); + printer->Print("{ .name = \"$short_name$\", .number = $name$ },\n", + "short_name", short_name, + "name", EnumValueName(all_values_[i])); + if (UnCamelCaseEnumShortName(short_name) != all_values_[i]->name()) { + text_format_decode_data.AddString(enum_value_description_key, short_name, + all_values_[i]->name()); + } + } + printer->Outdent(); + printer->Outdent(); + printer->Outdent(); + printer->Print(" };\n"); + if (text_format_decode_data.num_entries() == 0) { + printer->Print( + " descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n" + " values:values\n" + " valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription)\n" + " enumVerifier:$name$_IsValidValue];\n", + "name", name_); + } else { + printer->Print( + " static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n" + " descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n" + " values:values\n" + " valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription)\n" + " enumVerifier:$name$_IsValidValue\n" + " extraTextFormatInfo:extraTextFormatInfo];\n", + "name", name_, + "extraTextFormatInfo", CEscape(text_format_decode_data.Data())); + } + printer->Print( + " }\n" + " return descriptor;\n" + "}\n\n"); + + printer->Print( + "BOOL $name$_IsValidValue(int32_t value__) {\n" + " switch (value__) {\n", + "name", name_); + + for (int i = 0; i < base_values_.size(); i++) { + printer->Print( + " case $name$:\n", + "name", EnumValueName(base_values_[i])); + } + + printer->Print( + " return YES;\n" + " default:\n" + " return NO;\n" + " }\n" + "}\n\n"); +} +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.h b/src/google/protobuf/compiler/objectivec/objectivec_enum.h new file mode 100644 index 00000000..2dc5547b --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.h @@ -0,0 +1,73 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__ + +#include <string> +#include <set> +#include <vector> +#include <google/protobuf/descriptor.h> + +namespace google { +namespace protobuf { +namespace io { +class Printer; // printer.h +} +} + +namespace protobuf { +namespace compiler { +namespace objectivec { + +class EnumGenerator { + public: + EnumGenerator(const EnumDescriptor* descriptor); + ~EnumGenerator(); + + void GenerateHeader(io::Printer* printer); + void GenerateSource(io::Printer* printer); + + const string& name() const { return name_; } + + private: + const EnumDescriptor* descriptor_; + vector<const EnumValueDescriptor*> base_values_; + vector<const EnumValueDescriptor*> all_values_; + const string name_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator); +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc new file mode 100644 index 00000000..739282b2 --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc @@ -0,0 +1,129 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <map> +#include <string> + +#include <google/protobuf/compiler/objectivec/objectivec_enum_field.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/wire_format.h> +#include <google/protobuf/stubs/strutil.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +namespace { +void SetEnumVariables(const FieldDescriptor* descriptor, + map<string, string>* variables) { + string type = EnumName(descriptor->enum_type()); + (*variables)["storage_type"] = type; + // TODO(thomasvl): Make inclusion of descriptor compile time and output + // both of these. Note: Extensions currently have to have the EnumDescription. + (*variables)["enum_verifier"] = type + "_IsValidValue"; + (*variables)["enum_desc_func"] = type + "_EnumDescriptor"; + + const Descriptor* msg_descriptor = descriptor->containing_type(); + (*variables)["owning_message_class"] = ClassName(msg_descriptor); +} +} // namespace + +EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor) + : SingleFieldGenerator(descriptor) { + SetEnumVariables(descriptor, &variables_); +} + +EnumFieldGenerator::~EnumFieldGenerator() {} + +void EnumFieldGenerator::GenerateFieldDescriptionTypeSpecific( + io::Printer* printer) const { + // TODO(thomasvl): Output the CPP check to use descFunc or validator based + // on final compile. + printer->Print( + variables_, + " .typeSpecific.enumDescFunc = $enum_desc_func$,\n"); +} + +void EnumFieldGenerator::GenerateCFunctionDeclarations( + io::Printer* printer) const { + if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) return; + + printer->Print( + variables_, + "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message);\n" + "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value);\n" + "\n"); +} + +void EnumFieldGenerator::GenerateCFunctionImplementations( + io::Printer* printer) const { + if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) return; + + printer->Print( + variables_, + "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message) {\n" + " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n" + " GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n" + " return GPBGetInt32IvarWithField(message, field);\n" + "}\n" + "\n" + "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value) {\n" + " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n" + " GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n" + " GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);\n" + "}\n" + "\n"); +} + +RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator( + const FieldDescriptor* descriptor) + : RepeatedFieldGenerator(descriptor) { + SetEnumVariables(descriptor, &variables_); + variables_["array_storage_type"] = "GPBEnumArray"; +} + +RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} + +void RepeatedEnumFieldGenerator::GenerateFieldDescriptionTypeSpecific( + io::Printer* printer) const { + // TODO(thomasvl): Output the CPP check to use descFunc or validator based + // on final compile. + printer->Print( + variables_, + " .typeSpecific.enumDescFunc = $enum_desc_func$,\n"); +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h new file mode 100644 index 00000000..2d5822bb --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h @@ -0,0 +1,77 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__ + +#include <map> +#include <string> +#include <google/protobuf/compiler/objectivec/objectivec_field.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +class EnumFieldGenerator : public SingleFieldGenerator { + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); + + public: + virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const; + virtual void GenerateCFunctionDeclarations(io::Printer* printer) const; + virtual void GenerateCFunctionImplementations(io::Printer* printer) const; + + protected: + EnumFieldGenerator(const FieldDescriptor* descriptor); + virtual ~EnumFieldGenerator(); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); +}; + +class RepeatedEnumFieldGenerator : public RepeatedFieldGenerator { + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); + + public: + virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const; + + protected: + RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor); + virtual ~RepeatedEnumFieldGenerator(); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator); +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc new file mode 100644 index 00000000..b19c1b45 --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc @@ -0,0 +1,166 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <iostream> + +#include <google/protobuf/compiler/objectivec/objectivec_extension.h> +#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/io/printer.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +ExtensionGenerator::ExtensionGenerator(const string& root_class_name, + const FieldDescriptor* descriptor) + : method_name_(ExtensionMethodName(descriptor)), + root_class_and_method_name_(root_class_name + "_" + method_name_), + descriptor_(descriptor) { + // Extensions can be filtered via the method they are accessed off the + // file's Root with. + if (FilterClass(root_class_and_method_name_)) { + filter_reason_ = + string("Extension |") + root_class_and_method_name_ + "| was not whitelisted."; + } else { + // Extensions that add a Message field also require that field be allowed + // by the filter, or they aren't usable. + ObjectiveCType objc_type = GetObjectiveCType(descriptor_); + if (objc_type == OBJECTIVECTYPE_MESSAGE) { + const string message_class_name(ClassName(descriptor_->message_type())); + if (FilterClass(message_class_name)) { + filter_reason_ = string("Extension |") + root_class_and_method_name_ + + "| needs message |" + message_class_name + + "|, which was not whitelisted."; + } + } + } + if (descriptor->is_map()) { + // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some + // error case, so it seem to be ok to use as a back door for errors. + cerr << "error: Extension is a map<>!" + << " That used to be blocked by the compiler." << endl; + cerr.flush(); + abort(); + } +} + +ExtensionGenerator::~ExtensionGenerator() {} + +void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) { + WriteClassNameToClassList(root_class_and_method_name_); + if (IsFiltered()) { + printer->Print("// $filter_reason$\n\n", "filter_reason", filter_reason_); + return; + } + map<string, string> vars; + vars["method_name"] = method_name_; + SourceLocation location; + if (descriptor_->GetSourceLocation(&location)) { + vars["comments"] = BuildCommentsString(location); + } else { + vars["comments"] = ""; + } + printer->Print(vars, + "$comments$" + "+ (GPBExtensionField*)$method_name$;\n"); +} + +void ExtensionGenerator::GenerateStaticVariablesInitialization( + io::Printer* printer, bool* out_generated, bool root) { + if (IsFiltered()) { + return; + } + *out_generated = true; + map<string, string> vars; + vars["root_class_and_method_name"] = root_class_and_method_name_; + vars["extended_type"] = ClassName(descriptor_->containing_type()); + vars["number"] = SimpleItoa(descriptor_->number()); + + std::vector<string> options; + if (descriptor_->is_repeated()) options.push_back("GPBExtensionRepeated"); + if (descriptor_->options().packed()) options.push_back("GPBExtensionPacked"); + if (descriptor_->containing_type()->options().message_set_wire_format()) + options.push_back("GPBExtensionSetWireFormat"); + + vars["options"] = BuildFlagsString(options); + + ObjectiveCType objc_type = GetObjectiveCType(descriptor_); + string singular_type; + if (objc_type == OBJECTIVECTYPE_MESSAGE) { + vars["type"] = string("GPBStringifySymbol(") + + ClassName(descriptor_->message_type()) + ")"; + } else { + vars["type"] = "NULL"; + } + + vars["default_name"] = GPBValueFieldName(descriptor_); + if (descriptor_->is_repeated()) { + vars["default"] = "nil"; + } else { + vars["default"] = DefaultValue(descriptor_); + } + string type = GetCapitalizedType(descriptor_); + vars["extension_type"] = string("GPBType") + type; + + if (objc_type == OBJECTIVECTYPE_ENUM) { + vars["enum_desc_func_name"] = + EnumName(descriptor_->enum_type()) + "_EnumDescriptor"; + } else { + vars["enum_desc_func_name"] = "NULL"; + } + + printer->Print(vars, + "{\n" + " .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n" + " .type = $extension_type$,\n" + " .extendedClass = GPBStringifySymbol($extended_type$),\n" + " .fieldNumber = $number$,\n" + " .defaultValue.$default_name$ = $default$,\n" + " .messageOrGroupClassName = $type$,\n" + " .options = $options$,\n" + " .enumDescriptorFunc = $enum_desc_func_name$,\n" + "},\n"); +} + +void ExtensionGenerator::GenerateRegistrationSource(io::Printer* printer) { + if (IsFiltered()) { + return; + } + printer->Print( + "[registry addExtension:$root_class_and_method_name$];\n", + "root_class_and_method_name", root_class_and_method_name_); +} +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.h b/src/google/protobuf/compiler/objectivec/objectivec_extension.h new file mode 100644 index 00000000..d17f5be9 --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.h @@ -0,0 +1,73 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_EXTENSION_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_EXTENSION_H__ + +#include <google/protobuf/stubs/common.h> + +namespace google { +namespace protobuf { +class FieldDescriptor; // descriptor.h +namespace io { +class Printer; // printer.h +} +} + +namespace protobuf { +namespace compiler { +namespace objectivec { + +class ExtensionGenerator { + public: + explicit ExtensionGenerator(const string& root_class_name, + const FieldDescriptor* descriptor); + ~ExtensionGenerator(); + + void GenerateMembersHeader(io::Printer* printer); + void GenerateStaticVariablesInitialization(io::Printer* printer, + bool* out_generated, bool root); + void GenerateRegistrationSource(io::Printer* printer); + + bool IsFiltered() const { return filter_reason_.length() > 0; } + + private: + string method_name_; + string root_class_and_method_name_; + string filter_reason_; + const FieldDescriptor* descriptor_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); +}; +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc new file mode 100644 index 00000000..b071ce5d --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc @@ -0,0 +1,474 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <google/protobuf/compiler/objectivec/objectivec_field.h> +#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> +#include <google/protobuf/compiler/objectivec/objectivec_enum_field.h> +#include <google/protobuf/compiler/objectivec/objectivec_map_field.h> +#include <google/protobuf/compiler/objectivec/objectivec_message_field.h> +#include <google/protobuf/compiler/objectivec/objectivec_primitive_field.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/wire_format.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/strutil.h> + +#ifndef htonl +#include <netinet/in.h> +#endif + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +namespace { +void SetCommonFieldVariables(const FieldDescriptor* descriptor, + map<string, string>* variables) { + string camel_case_name = FieldName(descriptor); + string raw_field_name; + if (descriptor->type() == FieldDescriptor::TYPE_GROUP) { + raw_field_name = descriptor->message_type()->name(); + } else { + raw_field_name = descriptor->name(); + } + // The logic here has to match -[GGPBFieldDescriptor textFormatName]. + const string un_camel_case_name( + UnCamelCaseFieldName(camel_case_name, descriptor)); + const bool needs_custom_name = (raw_field_name != un_camel_case_name); + + SourceLocation location; + if (descriptor->GetSourceLocation(&location)) { + (*variables)["comments"] = BuildCommentsString(location); + } else { + (*variables)["comments"] = "\n"; + } + const string& classname = ClassName(descriptor->containing_type()); + (*variables)["classname"] = classname; + (*variables)["name"] = camel_case_name; + const string& capitalized_name = FieldNameCapitalized(descriptor); + (*variables)["capitalized_name"] = capitalized_name; + (*variables)["raw_field_name"] = raw_field_name; + (*variables)["field_number_name"] = + classname + "_FieldNumber_" + capitalized_name; + (*variables)["field_number"] = SimpleItoa(descriptor->number()); + (*variables)["has_index"] = SimpleItoa(descriptor->index()); + (*variables)["field_type"] = GetCapitalizedType(descriptor); + std::vector<string> field_flags; + if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated"); + if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired"); + if (descriptor->is_optional()) field_flags.push_back("GPBFieldOptional"); + if (descriptor->options().packed()) field_flags.push_back("GPBFieldPacked"); + + // ObjC custom flags. + if (descriptor->has_default_value()) + field_flags.push_back("GPBFieldHasDefaultValue"); + if (needs_custom_name) field_flags.push_back("GPBFieldTextFormatNameCustom"); + if (descriptor->type() == FieldDescriptor::TYPE_ENUM) { + // TODO(thomasvl): Output the CPP check to use descFunc or validator based + // on final compile. + field_flags.push_back("GPBFieldHasEnumDescriptor"); + } + + (*variables)["fieldflags"] = BuildFlagsString(field_flags); + + (*variables)["default"] = DefaultValue(descriptor); + (*variables)["default_name"] = GPBValueFieldName(descriptor); + + (*variables)["typeSpecific_name"] = "className"; + (*variables)["typeSpecific_value"] = "NULL"; + + string field_options = descriptor->options().SerializeAsString(); + // Must convert to a standard byte order for packing length into + // a cstring. + uint32_t length = htonl(field_options.length()); + if (length > 0) { + string bytes((const char*)&length, sizeof(length)); + bytes.append(field_options); + string options_str = "\"" + CEscape(bytes) + "\""; + (*variables)["fieldoptions"] = "\"" + CEscape(bytes) + "\""; + } else { + (*variables)["fieldoptions"] = ""; + } + + // Clear some common things so they can be set just when needed. + (*variables)["storage_attribute"] = ""; +} + +// A field generator that writes nothing. +class EmptyFieldGenerator : public FieldGenerator { + public: + EmptyFieldGenerator(const FieldDescriptor* descriptor, const string& reason) + : FieldGenerator(descriptor), reason_(reason) {} + virtual ~EmptyFieldGenerator() {} + + virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const {} + virtual void GeneratePropertyDeclaration(io::Printer* printer) const { + string name = FieldName(descriptor_); + string type; + switch (GetObjectiveCType(descriptor_)) { + case OBJECTIVECTYPE_MESSAGE: + type = ClassName(descriptor_->message_type()) + " *"; + break; + + case OBJECTIVECTYPE_ENUM: + type = EnumName(descriptor_->enum_type()) + " "; + break; + + default: + type = string(descriptor_->type_name()) + " "; + break; + } + printer->Print("// Field |$type$$name$| $reason$\n\n", "type", type, "name", + name, "reason", reason_); + } + + virtual void GenerateFieldNumberConstant(io::Printer* printer) const {} + virtual void GeneratePropertyImplementation(io::Printer* printer) const {} + virtual void GenerateFieldDescription(io::Printer* printer) const {} + + virtual bool WantsHasProperty(void) const { return false; } + + private: + string reason_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EmptyFieldGenerator); +}; + +} // namespace + +FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) { + FieldGenerator* result = NULL; + if (field->is_repeated()) { + switch (GetObjectiveCType(field)) { + case OBJECTIVECTYPE_MESSAGE: { + string type = ClassName(field->message_type()); + if (FilterClass(type)) { + string reason = + "Filtered by |" + type + "| not being whitelisted."; + result = new EmptyFieldGenerator(field, reason); + } else if (field->is_map()) { + result = new MapFieldGenerator(field); + } else { + result = new RepeatedMessageFieldGenerator(field); + } + break; + } + case OBJECTIVECTYPE_ENUM: + result = new RepeatedEnumFieldGenerator(field); + break; + default: + result = new RepeatedPrimitiveFieldGenerator(field); + break; + } + } else { + switch (GetObjectiveCType(field)) { + case OBJECTIVECTYPE_MESSAGE: { + string type = ClassName(field->message_type()); + if (FilterClass(type)) { + string reason = + "Filtered by |" + type + "| not being whitelisted."; + result = new EmptyFieldGenerator(field, reason); + } else { + result = new MessageFieldGenerator(field); + } + break; + } + case OBJECTIVECTYPE_ENUM: + result = new EnumFieldGenerator(field); + break; + default: + if (IsReferenceType(field)) { + result = new PrimitiveObjFieldGenerator(field); + } else { + result = new PrimitiveFieldGenerator(field); + } + break; + } + } + result->FinishInitialization(); + return result; +} + + +FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor) + : descriptor_(descriptor) { + SetCommonFieldVariables(descriptor, &variables_); +} + +FieldGenerator::~FieldGenerator() {} + +void FieldGenerator::GenerateFieldNumberConstant(io::Printer* printer) const { + printer->Print( + variables_, + "$field_number_name$ = $field_number$,\n"); +} + +void FieldGenerator::GenerateCFunctionDeclarations( + io::Printer* printer) const { + // Nothing +} + +void FieldGenerator::GenerateCFunctionImplementations( + io::Printer* printer) const { + // Nothing +} + +void FieldGenerator::GenerateFieldDescription( + io::Printer* printer) const { + printer->Print( + variables_, + "{\n" + " .name = \"$name$\",\n" + " .number = $field_number_name$,\n" + " .hasIndex = $has_index$,\n" + " .flags = $fieldflags$,\n" + " .type = GPBType$field_type$,\n" + " .offset = offsetof($classname$_Storage, $name$),\n" + " .defaultValue.$default_name$ = $default$,\n"); + + // " .typeSpecific.value* = [something]," + GenerateFieldDescriptionTypeSpecific(printer); + + const string& field_options(variables_.at("fieldoptions")); + if (field_options.empty()) { + printer->Print(" .fieldOptions = NULL,\n"); + } else { + // Can't use PrintRaw() here to get the #if/#else/#endif lines completely + // outdented because the need for indent captured on the previous + // printing of a \n and there is no way to get the current indent level + // to call the right number of Outdent()/Indents() to maintain state. + printer->Print( + variables_, + "#if GPBOBJC_INCLUDE_FIELD_OPTIONS\n" + " .fieldOptions = $fieldoptions$,\n" + "#else\n" + " .fieldOptions = NULL,\n" + "#endif // GPBOBJC_INCLUDE_FIELD_OPTIONS\n"); + } + + printer->Print("},\n"); +} + +void FieldGenerator::GenerateFieldDescriptionTypeSpecific( + io::Printer* printer) const { + printer->Print( + variables_, + " .typeSpecific.$typeSpecific_name$ = $typeSpecific_value$,\n"); +} + +void FieldGenerator::SetOneofIndexBase(int index_base) { + if (descriptor_->containing_oneof() != NULL) { + int index = descriptor_->containing_oneof()->index() + index_base; + // Flip the sign to mark it as a oneof. + variables_["has_index"] = SimpleItoa(-index);; + } +} + +void FieldGenerator::FinishInitialization(void) { + // Nothing +} + +SingleFieldGenerator::SingleFieldGenerator( + const FieldDescriptor* descriptor) + : FieldGenerator(descriptor) { + // Nothing +} + +SingleFieldGenerator::~SingleFieldGenerator() {} + +void SingleFieldGenerator::GenerateFieldStorageDeclaration( + io::Printer* printer) const { + printer->Print(variables_, "$storage_type$ $name$;\n"); +} + +void SingleFieldGenerator::GeneratePropertyDeclaration( + io::Printer* printer) const { + printer->Print(variables_, "$comments$"); + if (WantsHasProperty()) { + printer->Print( + variables_, + "@property(nonatomic, readwrite) BOOL has$capitalized_name$;\n"); + } + printer->Print( + variables_, + "@property(nonatomic, readwrite) $storage_type$ $name$;\n" + "\n"); +} + +void SingleFieldGenerator::GeneratePropertyImplementation( + io::Printer* printer) const { + if (WantsHasProperty()) { + printer->Print(variables_, "@dynamic has$capitalized_name$, $name$;\n"); + } else { + printer->Print(variables_, "@dynamic $name$;\n"); + } +} + +bool SingleFieldGenerator::WantsHasProperty(void) const { + if (descriptor_->containing_oneof() != NULL) { + // If in a oneof, it uses the oneofcase instead of a has bit. + return false; + } + if (HasFieldPresence(descriptor_->file())) { + // In proto1/proto2, every field has a has_$name$() method. + return true; + } + return false; +} + +ObjCObjFieldGenerator::ObjCObjFieldGenerator( + const FieldDescriptor* descriptor) + : SingleFieldGenerator(descriptor) { + variables_["property_storage_attribute"] = "strong"; + if (IsRetainedName(variables_["name"])) { + variables_["storage_attribute"] = " NS_RETURNS_NOT_RETAINED"; + } +} + +ObjCObjFieldGenerator::~ObjCObjFieldGenerator() {} + +void ObjCObjFieldGenerator::GenerateFieldStorageDeclaration( + io::Printer* printer) const { + printer->Print(variables_, "$storage_type$ *$name$;\n"); +} + +void ObjCObjFieldGenerator::GeneratePropertyDeclaration( + io::Printer* printer) const { + + // Differs from SingleFieldGenerator::GeneratePropertyDeclaration() in that + // it uses pointers and deals with Objective C's rules around storage name + // conventions (init*, new*, etc.) + + printer->Print(variables_, "$comments$"); + if (WantsHasProperty()) { + printer->Print( + variables_, + "@property(nonatomic, readwrite) BOOL has$capitalized_name$;\n"); + } + printer->Print( + variables_, + "@property(nonatomic, readwrite, $property_storage_attribute$) $storage_type$ *$name$$storage_attribute$;\n"); + if (IsInitName(variables_.at("name"))) { + // If property name starts with init we need to annotate it to get past ARC. + // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227 + printer->Print(variables_, + "- ($storage_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n"); + } + printer->Print("\n"); +} + +RepeatedFieldGenerator::RepeatedFieldGenerator( + const FieldDescriptor* descriptor) + : ObjCObjFieldGenerator(descriptor) { + // Repeated fields don't use the has index. + variables_["has_index"] = "GPBNoHasBit"; +} + +RepeatedFieldGenerator::~RepeatedFieldGenerator() {} + +void RepeatedFieldGenerator::FinishInitialization(void) { + FieldGenerator::FinishInitialization(); + variables_["array_comment"] = + "// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n"; +} + +void RepeatedFieldGenerator::GenerateFieldStorageDeclaration( + io::Printer* printer) const { + printer->Print(variables_, "$array_storage_type$ *$name$;\n"); +} + +void RepeatedFieldGenerator::GeneratePropertyImplementation( + io::Printer* printer) const { + printer->Print(variables_, "@dynamic $name$;\n"); +} + +void RepeatedFieldGenerator::GeneratePropertyDeclaration( + io::Printer* printer) const { + + // Repeated fields don't need the has* properties, but this has the same + // logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for dealing + // with needing Objective C's rules around storage name conventions (init*, + // new*, etc.) + + printer->Print( + variables_, + "$comments$" + "$array_comment$" + "@property(nonatomic, readwrite, strong) $array_storage_type$ *$name$$storage_attribute$;\n"); + if (IsInitName(variables_.at("name"))) { + // If property name starts with init we need to annotate it to get past ARC. + // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227 + printer->Print(variables_, + "- ($array_storage_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n"); + } + printer->Print("\n"); +} + +bool RepeatedFieldGenerator::WantsHasProperty(void) const { + // Consumer check the array size/existance rather than a has bit. + return false; +} + +FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor) + : descriptor_(descriptor), + field_generators_( + new scoped_ptr<FieldGenerator>[descriptor->field_count()]), + extension_generators_( + new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) { + // Construct all the FieldGenerators. + for (int i = 0; i < descriptor->field_count(); i++) { + field_generators_[i].reset(FieldGenerator::Make(descriptor->field(i))); + } + for (int i = 0; i < descriptor->extension_count(); i++) { + extension_generators_[i].reset(FieldGenerator::Make(descriptor->extension(i))); + } +} + +FieldGeneratorMap::~FieldGeneratorMap() {} + +const FieldGenerator& FieldGeneratorMap::get( + const FieldDescriptor* field) const { + GOOGLE_CHECK_EQ(field->containing_type(), descriptor_); + return *field_generators_[field->index()]; +} + +const FieldGenerator& FieldGeneratorMap::get_extension(int index) const { + return *extension_generators_[index]; +} + +void FieldGeneratorMap::SetOneofIndexBase(int index_base) { + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_[i]->SetOneofIndexBase(index_base); + } +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.h b/src/google/protobuf/compiler/objectivec/objectivec_field.h new file mode 100644 index 00000000..c65e73b2 --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.h @@ -0,0 +1,166 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__ + +#include <map> +#include <string> +#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/descriptor.h> + +namespace google { +namespace protobuf { + +namespace io { +class Printer; // printer.h +} // namespace io + +namespace compiler { +namespace objectivec { + +class FieldGenerator { + public: + static FieldGenerator* Make(const FieldDescriptor* field); + + virtual ~FieldGenerator(); + + virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const = 0; + virtual void GeneratePropertyDeclaration(io::Printer* printer) const = 0; + + virtual void GeneratePropertyImplementation(io::Printer* printer) const = 0; + + virtual void GenerateFieldDescription(io::Printer* printer) const; + virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const; + virtual void GenerateFieldNumberConstant(io::Printer* printer) const; + + virtual void GenerateCFunctionDeclarations(io::Printer* printer) const; + virtual void GenerateCFunctionImplementations(io::Printer* printer) const; + + void SetOneofIndexBase(int index_base); + + string variable(const char* key) const { + return variables_.find(key)->second; + } + + bool needs_textformat_name_support() const { + const string& field_flags = variable("fieldflags"); + return field_flags.find("GPBFieldTextFormatNameCustom") != string::npos; + } + string generated_objc_name() const { return variable("name"); } + string raw_field_name() const { return variable("raw_field_name"); } + + protected: + FieldGenerator(const FieldDescriptor* descriptor); + + virtual void FinishInitialization(void); + virtual bool WantsHasProperty(void) const = 0; + + const FieldDescriptor* descriptor_; + map<string, string> variables_; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator); +}; + +class SingleFieldGenerator : public FieldGenerator { + public: + virtual ~SingleFieldGenerator(); + + virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const; + virtual void GeneratePropertyDeclaration(io::Printer* printer) const; + + virtual void GeneratePropertyImplementation(io::Printer* printer) const; + + protected: + SingleFieldGenerator(const FieldDescriptor* descriptor); + virtual bool WantsHasProperty(void) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingleFieldGenerator); +}; + +// Subclass with common support for when the field ends up as an ObjC Object. +class ObjCObjFieldGenerator : public SingleFieldGenerator { + public: + virtual ~ObjCObjFieldGenerator(); + + virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const; + virtual void GeneratePropertyDeclaration(io::Printer* printer) const; + + protected: + ObjCObjFieldGenerator(const FieldDescriptor* descriptor); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjCObjFieldGenerator); +}; + +class RepeatedFieldGenerator : public ObjCObjFieldGenerator { + public: + virtual ~RepeatedFieldGenerator(); + + virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const; + virtual void GeneratePropertyDeclaration(io::Printer* printer) const; + + virtual void GeneratePropertyImplementation(io::Printer* printer) const; + + protected: + RepeatedFieldGenerator(const FieldDescriptor* descriptor); + virtual void FinishInitialization(void); + virtual bool WantsHasProperty(void) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedFieldGenerator); +}; + +// Convenience class which constructs FieldGenerators for a Descriptor. +class FieldGeneratorMap { + public: + FieldGeneratorMap(const Descriptor* descriptor); + ~FieldGeneratorMap(); + + const FieldGenerator& get(const FieldDescriptor* field) const; + const FieldGenerator& get_extension(int index) const; + + void SetOneofIndexBase(int index_base); + + private: + const Descriptor* descriptor_; + scoped_array<scoped_ptr<FieldGenerator> > field_generators_; + scoped_array<scoped_ptr<FieldGenerator> > extension_generators_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); +}; +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc new file mode 100644 index 00000000..f1e8c0a0 --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc @@ -0,0 +1,392 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <google/protobuf/compiler/objectivec/objectivec_file.h> +#include <google/protobuf/compiler/objectivec/objectivec_enum.h> +#include <google/protobuf/compiler/objectivec/objectivec_extension.h> +#include <google/protobuf/compiler/objectivec/objectivec_message.h> +#include <google/protobuf/compiler/code_generator.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/stubs/stl_util.h> +#include <google/protobuf/stubs/strutil.h> +#include <sstream> + +// This is also found in GPBBootstrap.h, and needs to be kept in sync. It +// is the version check done to ensure generated code works with the current +// runtime being used. +const int32_t GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30000; + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { +FileGenerator::FileGenerator(const FileDescriptor *file) + : file_(file), + root_class_name_(FileClassName(file)), + is_filtered_(true), + all_extensions_filtered_(true) { + for (int i = 0; i < file_->enum_type_count(); i++) { + EnumGenerator *generator = new EnumGenerator(file_->enum_type(i)); + // The enums are exposed via C functions, so they will dead strip if + // not used. + is_filtered_ &= false; + enum_generators_.push_back(generator); + } + for (int i = 0; i < file_->message_type_count(); i++) { + MessageGenerator *generator = + new MessageGenerator(root_class_name_, file_->message_type(i)); + is_filtered_ &= generator->IsFiltered(); + is_filtered_ &= generator->IsSubContentFiltered(); + message_generators_.push_back(generator); + } + for (int i = 0; i < file_->extension_count(); i++) { + ExtensionGenerator *generator = + new ExtensionGenerator(root_class_name_, file_->extension(i)); + is_filtered_ &= generator->IsFiltered(); + all_extensions_filtered_ &= generator->IsFiltered(); + extension_generators_.push_back(generator); + } + // If there is nothing in the file we filter it. +} + +FileGenerator::~FileGenerator() { + STLDeleteContainerPointers(dependency_generators_.begin(), + dependency_generators_.end()); + STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end()); + STLDeleteContainerPointers(message_generators_.begin(), + message_generators_.end()); + STLDeleteContainerPointers(extension_generators_.begin(), + extension_generators_.end()); +} + +void FileGenerator::GenerateHeader(io::Printer *printer) { + printer->Print( + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// source: $filename$\n" + "\n", + "filename", file_->name()); + + printer->Print("#import \"GPBProtocolBuffers.h\"\n\n"); + + // Add some verification that the generated code matches the source the + // code is being compiled with. + printer->Print( + "#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != $protoc_gen_objc_version$\n" + "#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources.\n" + "#endif\n" + "\n", + "protoc_gen_objc_version", + SimpleItoa(GOOGLE_PROTOBUF_OBJC_GEN_VERSION)); + + if (!IsFiltered()) { + const vector<FileGenerator *> &dependency_generators = + DependencyGenerators(); + if (dependency_generators.size() > 0) { + for (vector<FileGenerator *>::const_iterator iter = + dependency_generators.begin(); + iter != dependency_generators.end(); ++iter) { + printer->Print("#import \"$header$.pbobjc.h\"\n", + "header", (*iter)->Path()); + } + printer->Print("\n"); + } + } + + printer->Print("CF_EXTERN_C_BEGIN\n\n"); + + if (!IsFiltered()) { + set<string> dependencies; + DetermineDependencies(&dependencies); + for (set<string>::const_iterator i(dependencies.begin()); + i != dependencies.end(); ++i) { + printer->Print("$value$;\n", "value", *i); + } + + if (dependencies.begin() != dependencies.end()) { + printer->Print("\n"); + } + } + + // need to write out all enums first + for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin(); + iter != enum_generators_.end(); ++iter) { + (*iter)->GenerateHeader(printer); + } + + for (vector<MessageGenerator *>::iterator iter = message_generators_.begin(); + iter != message_generators_.end(); ++iter) { + (*iter)->GenerateEnumHeader(printer); + } + + // For extensions to chain together, the Root gets created even if there + // are no extensions. So if the entire file isn't filtered away, output it. + if (!IsFiltered()) { + printer->Print( + "\n" + "#pragma mark - $root_class_name$\n" + "\n" + "@interface $root_class_name$ : GPBRootObject\n" + "@end\n\n", + "root_class_name", root_class_name_); + } + + if (extension_generators_.size() > 0) { + // The dynamic methods block is only needed if there are extensions. If + // they are all filtered, output the @interface as a comment so there is + // something left in the header for anyone that looks. + const char *root_line_prefix = ""; + if (AreAllExtensionsFiltered()) { + root_line_prefix = "// "; + } + printer->Print( + "$root_line_prefix$@interface $root_class_name$ (DynamicMethods)\n", + "root_class_name", root_class_name_, + "root_line_prefix", root_line_prefix); + + for (vector<ExtensionGenerator *>::iterator iter = + extension_generators_.begin(); + iter != extension_generators_.end(); ++iter) { + (*iter)->GenerateMembersHeader(printer); + } + + printer->Print("$root_line_prefix$@end\n\n", + "root_line_prefix", root_line_prefix); + } // extension_generators_.size() > 0 + + for (vector<MessageGenerator *>::iterator iter = message_generators_.begin(); + iter != message_generators_.end(); ++iter) { + (*iter)->GenerateMessageHeader(printer); + } + + printer->Print("CF_EXTERN_C_END\n"); +} + +void DetermineDependenciesWorker(set<string> *dependencies, + set<string> *seen_files, + const string &classname, + const FileDescriptor *file) { + if (seen_files->find(file->name()) != seen_files->end()) { + // don't infinitely recurse + return; + } + + seen_files->insert(file->name()); + + for (int i = 0; i < file->dependency_count(); i++) { + DetermineDependenciesWorker(dependencies, seen_files, classname, + file->dependency(i)); + } + for (int i = 0; i < file->message_type_count(); i++) { + MessageGenerator(classname, file->message_type(i)) + .DetermineDependencies(dependencies); + } +} + +void FileGenerator::DetermineDependencies(set<string> *dependencies) { + set<string> seen_files; + DetermineDependenciesWorker(dependencies, &seen_files, root_class_name_, + file_); +} + +void FileGenerator::GenerateSource(io::Printer *printer) { + printer->Print( + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// source: $filename$\n" + "\n", + "filename", file_->name()); + + if (IsFiltered()) { + printer->Print( + "// File empty because all messages, extensions and enum have been filtered.\n" + "\n" + "\n" + "// Dummy symbol that will be stripped but will avoid linker warnings about\n" + "// no symbols in the .o form compiling this file.\n" + "static int $root_class_name$_dummy __attribute__((unused,used)) = 0;\n", + "root_class_name", root_class_name_); + return; + } + + printer->Print("#import \"GPBProtocolBuffers_RuntimeSupport.h\"\n\n"); + + string header_file = Path() + ".pbobjc.h"; + + printer->Print( + "#import \"$header_file$\"\n" + "\n" + "#pragma mark - $root_class_name$\n" + "\n" + "@implementation $root_class_name$\n\n", + "header_file", header_file, + "root_class_name", root_class_name_); + + bool generated_extensions = false; + if (file_->extension_count() + file_->message_type_count() + + file_->dependency_count() > + 0) { + ostringstream extensions_stringstream; + + if (file_->extension_count() + file_->message_type_count() > 0) { + io::OstreamOutputStream extensions_outputstream(&extensions_stringstream); + io::Printer extensions_printer(&extensions_outputstream, '$'); + extensions_printer.Print( + "static GPBExtensionDescription descriptions[] = {\n"); + extensions_printer.Indent(); + for (vector<ExtensionGenerator *>::iterator iter = + extension_generators_.begin(); + iter != extension_generators_.end(); ++iter) { + (*iter)->GenerateStaticVariablesInitialization( + &extensions_printer, &generated_extensions, true); + } + for (vector<MessageGenerator *>::iterator iter = + message_generators_.begin(); + iter != message_generators_.end(); ++iter) { + (*iter)->GenerateStaticVariablesInitialization(&extensions_printer, + &generated_extensions); + } + extensions_printer.Outdent(); + extensions_printer.Print("};\n"); + if (generated_extensions) { + extensions_printer.Print( + "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n" + " GPBExtensionField *extension = [[GPBExtensionField alloc] initWithDescription:&descriptions[i]];\n" + " [registry addExtension:extension];\n" + " [self globallyRegisterExtension:extension];\n" + " [extension release];\n" + "}\n"); + } else { + extensions_printer.Print("#pragma unused (descriptions)\n"); + } + const vector<FileGenerator *> &dependency_generators = + DependencyGenerators(); + if (dependency_generators.size()) { + for (vector<FileGenerator *>::const_iterator iter = + dependency_generators.begin(); + iter != dependency_generators.end(); ++iter) { + if (!(*iter)->IsFiltered()) { + extensions_printer.Print( + "[registry addExtensions:[$dependency$ extensionRegistry]];\n", + "dependency", (*iter)->RootClassName()); + generated_extensions = true; + } + } + } else if (!generated_extensions) { + extensions_printer.Print("#pragma unused (registry)\n"); + } + } + + if (generated_extensions) { + printer->Print( + "+ (GPBExtensionRegistry*)extensionRegistry {\n" + " // This is called by +initialize so there is no need to worry\n" + " // about thread safety and initialization of registry.\n" + " static GPBExtensionRegistry* registry = nil;\n" + " if (!registry) {\n" + " registry = [[GPBExtensionRegistry alloc] init];\n"); + + printer->Indent(); + printer->Indent(); + + extensions_stringstream.flush(); + printer->Print(extensions_stringstream.str().c_str()); + printer->Outdent(); + printer->Outdent(); + + printer->Print( + " }\n" + " return registry;\n" + "}\n" + "\n" + "+ (void)load {\n" + " @autoreleasepool {\n" + " [self extensionRegistry]; // Construct extension registry.\n" + " }\n" + "}\n\n"); + } + } + + printer->Print("@end\n\n"); + + + string syntax; + switch (file_->syntax()) { + case FileDescriptor::SYNTAX_UNKNOWN: + syntax = "GPBFileSyntaxUnknown"; + break; + case FileDescriptor::SYNTAX_PROTO2: + syntax = "GPBFileSyntaxProto2"; + break; + case FileDescriptor::SYNTAX_PROTO3: + syntax = "GPBFileSyntaxProto3"; + break; + } + printer->Print( + "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n" + " // This is called by +initialize so there is no need to worry\n" + " // about thread safety of the singleton.\n" + " static GPBFileDescriptor *descriptor = NULL;\n" + " if (!descriptor) {\n" + " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" + " syntax:$syntax$];\n" + " }\n" + " return descriptor;\n" + "}\n" + "\n", + "root_class_name", root_class_name_, + "package", file_->package(), + "syntax", syntax); + + for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin(); + iter != enum_generators_.end(); ++iter) { + (*iter)->GenerateSource(printer); + } + for (vector<MessageGenerator *>::iterator iter = message_generators_.begin(); + iter != message_generators_.end(); ++iter) { + (*iter)->GenerateSource(printer); + } +} + +const string FileGenerator::Path() const { return FilePath(file_); } + +const vector<FileGenerator *> &FileGenerator::DependencyGenerators() { + if (file_->dependency_count() != dependency_generators_.size()) { + for (int i = 0; i < file_->dependency_count(); i++) { + FileGenerator *generator = new FileGenerator(file_->dependency(i)); + dependency_generators_.push_back(generator); + } + } + return dependency_generators_; +} +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h new file mode 100644 index 00000000..fbd08eae --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.h @@ -0,0 +1,94 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__ + +#include <string> +#include <set> +#include <vector> +#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> +#include <google/protobuf/stubs/common.h> + +namespace google { +namespace protobuf { +class FileDescriptor; // descriptor.h +namespace io { +class Printer; // printer.h +} +} + +namespace protobuf { +namespace compiler { +namespace objectivec { + +class EnumGenerator; +class ExtensionGenerator; +class MessageGenerator; + +class FileGenerator { + public: + explicit FileGenerator(const FileDescriptor* file); + ~FileGenerator(); + + void GenerateSource(io::Printer* printer); + void GenerateHeader(io::Printer* printer); + + const string& RootClassName() const { return root_class_name_; } + const string Path() const; + + bool IsFiltered() const { return is_filtered_; } + bool AreAllExtensionsFiltered() const { return all_extensions_filtered_; } + + private: + const FileDescriptor* file_; + string root_class_name_; + + // Access this field through the DependencyGenerators accessor call below. + // Do not reference it directly. + vector<FileGenerator*> dependency_generators_; + + vector<EnumGenerator*> enum_generators_; + vector<MessageGenerator*> message_generators_; + vector<ExtensionGenerator*> extension_generators_; + bool is_filtered_; + bool all_extensions_filtered_; + + void DetermineDependencies(set<string>* dependencies); + + const vector<FileGenerator*>& DependencyGenerators(); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); +}; +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc new file mode 100644 index 00000000..1eb31a79 --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc @@ -0,0 +1,95 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <iostream> +#include <google/protobuf/compiler/objectivec/objectivec_generator.h> +#include <google/protobuf/compiler/objectivec/objectivec_file.h> +#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/stubs/strutil.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +ObjectiveCGenerator::ObjectiveCGenerator() {} + +ObjectiveCGenerator::~ObjectiveCGenerator() {} + +bool ObjectiveCGenerator::Generate(const FileDescriptor* file, + const string& parameter, + OutputDirectory* output_directory, + string* error) const { + // ObjC doesn't have any options at the moment, error if passed one. + vector<pair<string, string> > options; + ParseGeneratorParameter(parameter, &options); + for (int i = 0; i < options.size(); i++) { + *error = "error:: Unknown generator option: " + options[i].first; + return false; + } + + if (!InitializeClassWhitelist(error)) { + return false; + } + + FileGenerator file_generator(file); + + string filepath = FilePath(file); + + // Generate header. + { + scoped_ptr<io::ZeroCopyOutputStream> output( + output_directory->Open(filepath + ".pbobjc.h")); + io::Printer printer(output.get(), '$'); + file_generator.GenerateHeader(&printer); + } + + // Generate m file. + { + scoped_ptr<io::ZeroCopyOutputStream> output( + output_directory->Open(filepath + ".pbobjc.m")); + io::Printer printer(output.get(), '$'); + file_generator.GenerateSource(&printer); + } + + if (!WriteClassList(error)) { + return false; + } + + return true; +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.h b/src/google/protobuf/compiler/objectivec/objectivec_generator.h new file mode 100644 index 00000000..24286ac9 --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.h @@ -0,0 +1,60 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Generates ObjectiveC code for a given .proto file. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__ + +#include <string> +#include <google/protobuf/compiler/code_generator.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +class LIBPROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator { + public: + ObjectiveCGenerator(); + ~ObjectiveCGenerator(); + + // implements CodeGenerator ---------------------------------------- + bool Generate(const FileDescriptor* file, const string& parameter, + OutputDirectory* output_directory, string* error) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectiveCGenerator); +}; +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc new file mode 100644 index 00000000..a4eba09b --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc @@ -0,0 +1,1131 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <arpa/inet.h> +#include <errno.h> +#include <limits.h> +#include <stdlib.h> +#include <unistd.h> + +#include <fstream> +#include <iostream> +#include <sstream> +#include <vector> + +#include <google/protobuf/stubs/hash.h> +#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/stubs/strutil.h> + +#ifndef htonl +#include <netinet/in.h> +#endif + +#ifndef O_EXLOCK +#include <sys/file.h> +#endif + +// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some +// error case, so it seem to be ok to use as a back door for errors. + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +namespace { + +hash_set<string> gClassWhitelist; +stringstream gClassListStream; + +// islower()/isupper()/tolower()/toupper() change based on locale. + +bool IsLower(const char c) { + return ('a' <= c && c <= 'z'); +} + +bool IsUpper(const char c) { + return ('A' <= c && c <= 'Z'); +} + +char ToLower(char c) { + if ('A' <= c && c <= 'Z') { + c += 'a' - 'A'; + } + return c; +} + +// toupper() changes based on locale. We don't want this! +char ToUpper(char c) { + if ('a' <= c && c <= 'z') { + c += 'A' - 'a'; + } + return c; +} + +string TrimString(const string& s) { + string::size_type start = s.find_first_not_of(" \n\r\t"); + if (start == string::npos) { + return ""; + } + string::size_type end = s.find_last_not_of(" \n\r\t") + 1; + return s.substr(start, end - start); +} + +hash_set<string> MakeWordsMap(const char* const words[], size_t num_words) { + hash_set<string> result; + for (int i = 0; i < num_words; i++) { + result.insert(words[i]); + } + return result; +} + +const char* const kUpperSegmentsList[] = {"url", "http", "https"}; + +hash_set<string> kUpperSegments = + MakeWordsMap(kUpperSegmentsList, GOOGLE_ARRAYSIZE(kUpperSegmentsList)); + +// Internal helper for name handing. +// Do not expose this outside of helpers, stick to having functions for specific +// cases (ClassName(), FieldName()), so there is always consistent suffix rules. +string UnderscoresToCamelCase(const string& input, bool first_capitalized) { + vector<string> values; + string current; + + bool last_char_was_number = false; + bool last_char_was_lower = false; + bool last_char_was_upper = false; + for (int i = 0; i < input.size(); i++) { + char c = input[i]; + if (c >= '0' && c <= '9') { + if (!last_char_was_number) { + values.push_back(current); + current = ""; + } + current += c; + last_char_was_number = last_char_was_lower = last_char_was_upper = false; + last_char_was_number = true; + } else if (IsLower(c)) { + // lowercase letter can follow a lowercase or uppercase letter + if (!last_char_was_lower && !last_char_was_upper) { + values.push_back(current); + current = ""; + } + current += c; // already lower + last_char_was_number = last_char_was_lower = last_char_was_upper = false; + last_char_was_lower = true; + } else if (IsUpper(c)) { + if (!last_char_was_upper) { + values.push_back(current); + current = ""; + } + current += ToLower(c); + last_char_was_number = last_char_was_lower = last_char_was_upper = false; + last_char_was_upper = true; + } else { + last_char_was_number = last_char_was_lower = last_char_was_upper = false; + } + } + values.push_back(current); + + for (vector<string>::iterator i = values.begin(); i != values.end(); ++i) { + string value = *i; + bool all_upper = (kUpperSegments.count(value) > 0); + for (int j = 0; j < value.length(); j++) { + if (j == 0 || all_upper) { + value[j] = ToUpper(value[j]); + } else { + // Nothing, already in lower. + } + } + *i = value; + } + string result; + for (vector<string>::iterator i = values.begin(); i != values.end(); ++i) { + result += *i; + } + if ((result.length() != 0) && !first_capitalized) { + result[0] = ToLower(result[0]); + } + return result; +} + +const char* const kReservedWordList[] = { + // Objective C "keywords" that aren't in C + // From + // http://stackoverflow.com/questions/1873630/reserved-keywords-in-objective-c + "id", "_cmd", "super", "in", "out", "inout", "bycopy", "byref", "oneway", + "self", + + // C/C++ keywords (Incl C++ 0x11) + // From http://en.cppreference.com/w/cpp/keywords + "and", "and_eq", "alignas", "alignof", "asm", "auto", "bitand", "bitor", + "bool", "break", "case", "catch", "char", "char16_t", "char32_t", "class", + "compl", "const", "constexpr", "const_cast", "continue", "decltype", + "default", "delete", "double", "dynamic_cast", "else", "enum", "explicit", + "export", "extern ", "false", "float", "for", "friend", "goto", "if", + "inline", "int", "long", "mutable", "namespace", "new", "noexcept", "not", + "not_eq", "nullptr", "operator", "or", "or_eq", "private", "protected", + "public", "register", "reinterpret_cast", "return", "short", "signed", + "sizeof", "static", "static_assert", "static_cast", "struct", "switch", + "template", "this", "thread_local", "throw", "true", "try", "typedef", + "typeid", "typename", "union", "unsigned", "using", "virtual", "void", + "volatile", "wchar_t", "while", "xor", "xor_eq", + + // C99 keywords + // From + // http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fkeyw.htm + "restrict", + + // Objective-C Runtime typedefs + // From <obc/runtime.h> + "Category", "Ivar", "Method", "Protocol", + + // NSObject Methods + // new is covered by C++ keywords. + "description", "debugDescription", "finalize", "hash", "dealloc", "init", + "class", "superclass", "retain", "release", "autorelease", "retainCount", + "zone", "isProxy", "copy", "mutableCopy", "classForCoder", + + // GPBMessage Methods + // Only need to add instance methods that may conflict with + // method declared in protos. The main cases are methods + // that take no arguments, or setFoo:/hasFoo: type methods. + // These are currently in the same order as in GPBMessage.h. + "unknownFields", "extensionRegistry", "isInitialized", + "data", "delimitedData", "serializedSize", + "descriptor", "extensionsCurrentlySet", "clear", "sortedExtensionsInUse", + + // MacTypes.h names + "Fixed", "Fract", "Size", "LogicalAddress", "PhysicalAddress", "ByteCount", + "ByteOffset", "Duration", "AbsoluteTime", "OptionBits", "ItemCount", + "PBVersion", "ScriptCode", "LangCode", "RegionCode", "OSType", + "ProcessSerialNumber", "Point", "Rect", "FixedPoint", "FixedRect", "Style", + "StyleParameter", "StyleField", "TimeScale", "TimeBase", "TimeRecord", +}; + +hash_set<string> kReservedWords = + MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList)); + +string SanitizeNameForObjC(const string& input, const string& extension) { + if (kReservedWords.count(input) > 0) { + return input + extension; + } + return input; +} + +string NameFromFieldDescriptor(const FieldDescriptor* field) { + if (field->type() == FieldDescriptor::TYPE_GROUP) { + return field->message_type()->name(); + } else { + return field->name(); + } +} + +// Escape C++ trigraphs by escaping question marks to \? +string EscapeTrigraphs(const string& to_escape) { + return StringReplace(to_escape, "?", "\\?", true); +} + +void PathSplit(const string& path, string* directory, string* basename) { + string::size_type last_slash = path.rfind('/'); + if (last_slash == string::npos) { + if (directory) { + *directory = ""; + } + if (basename) { + *basename = path; + } + } else { + if (directory) { + *directory = path.substr(0, last_slash); + } + if (basename) { + *basename = path.substr(last_slash + 1); + } + } +} + +bool IsSpecialName(const string& name, const string* special_names, + size_t count) { + for (size_t i = 0; i < count; ++i) { + size_t length = special_names[i].length(); + if (name.compare(0, length, special_names[i]) == 0) { + if (name.length() > length) { + // If name is longer than the retained_name[i] that it matches + // the next character must be not lower case (newton vs newTon vs + // new_ton). + return !IsLower(name[length]); + } else { + return true; + } + } + } + return false; +} + +} // namespace + +string StripProto(const string& filename) { + if (HasSuffixString(filename, ".protodevel")) { + return StripSuffixString(filename, ".protodevel"); + } else { + return StripSuffixString(filename, ".proto"); + } +} + +bool IsRetainedName(const string& name) { + // List of prefixes from + // http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html + static const string retained_names[] = {"new", "alloc", "copy", + "mutableCopy"}; + return IsSpecialName(name, retained_names, + sizeof(retained_names) / sizeof(retained_names[0])); +} + +bool IsInitName(const string& name) { + static const string init_names[] = {"init"}; + return IsSpecialName(name, init_names, + sizeof(init_names) / sizeof(init_names[0])); +} + +string BaseFileName(const FileDescriptor* file) { + string basename; + PathSplit(file->name(), NULL, &basename); + return basename; +} + +string FileName(const FileDescriptor* file) { + string path = FilePath(file); + string basename; + PathSplit(path, NULL, &basename); + return basename; +} + +string FilePath(const FileDescriptor* file) { + string output; + string basename; + string directory; + PathSplit(file->name(), &directory, &basename); + if (directory.length() > 0) { + output = directory + "/"; + } + basename = StripProto(basename); + + // CamelCase to be more ObjC friendly. + basename = UnderscoresToCamelCase(basename, true); + + output += basename; + return output; +} + +string FileClassPrefix(const FileDescriptor* file) { + // Default is empty string, no need to check has_objc_class_prefix. + return file->options().objc_class_prefix(); +} + +string FileClassName(const FileDescriptor* file) { + string name = FileClassPrefix(file); + name += UnderscoresToCamelCase(StripProto(BaseFileName(file)), true); + name += "Root"; + // There aren't really any reserved words that end in "Root", but playing + // it safe and checking. + return SanitizeNameForObjC(name, "_RootClass"); +} + +string ClassNameWorker(const Descriptor* descriptor) { + string name; + if (descriptor->containing_type() != NULL) { + name = ClassNameWorker(descriptor->containing_type()); + name += "_"; + } + return name + descriptor->name(); +} + +string ClassNameWorker(const EnumDescriptor* descriptor) { + string name; + if (descriptor->containing_type() != NULL) { + name = ClassNameWorker(descriptor->containing_type()); + name += "_"; + } + return name + descriptor->name(); +} + +string ClassName(const Descriptor* descriptor) { + // 1. Message names are used as is (style calls for CamelCase, trust it). + // 2. Check for reserved word at the very end and then suffix things. + string prefix = FileClassPrefix(descriptor->file()); + string name = ClassNameWorker(descriptor); + return SanitizeNameForObjC(prefix + name, "_Class"); +} + +string EnumName(const EnumDescriptor* descriptor) { + // 1. Enum names are used as is (style calls for CamelCase, trust it). + // 2. Check for reserved word at the every end and then suffix things. + // message Fixed { + // message Size {...} + // enum Mumble {...} + // ... + // } + // yields Fixed_Class, Fixed_Size. + string name = FileClassPrefix(descriptor->file()); + name += ClassNameWorker(descriptor); + return SanitizeNameForObjC(name, "_Enum"); +} + +string EnumValueName(const EnumValueDescriptor* descriptor) { + // Because of the Switch enum compatibility, the name on the enum has to have + // the suffix handing, so it slightly diverges from how nested classes work. + // enum Fixed { + // FOO = 1 + // } + // yields Fixed_Enum and Fixed_Enum_Foo (not Fixed_Foo). + const string& class_name = EnumName(descriptor->type()); + const string& value_str = UnderscoresToCamelCase(descriptor->name(), true); + const string& name = class_name + "_" + value_str; + // There aren't really any reserved words with an underscore and a leading + // capital letter, but playing it safe and checking. + return SanitizeNameForObjC(name, "_Value"); +} + +string EnumValueShortName(const EnumValueDescriptor* descriptor) { + // Enum value names (EnumValueName above) are the enum name turned into + // a class name and then the value name is CamelCased and concatenated; the + // whole thing then gets sanitized for reserved words. + // The "short name" is intended to be the final leaf, the value name; but + // you can't simply send that off to sanitize as that could result in it + // getting modified when the full name didn't. For example enum + // "StorageModes" has a value "retain". So the full name is + // "StorageModes_Retain", but if we sanitize "retain" it would become + // "RetainValue". + // So the right way to get the short name is to take the full enum name + // and then strip off the enum name (leaving the value name and anything + // done by sanitize). + const string& class_name = EnumName(descriptor->type()); + const string& long_name_prefix = class_name + "_"; + const string& long_name = EnumValueName(descriptor); + return StripPrefixString(long_name, long_name_prefix); +} + +string UnCamelCaseEnumShortName(const string& name) { + string result; + for (int i = 0; i < name.size(); i++) { + char c = name[i]; + if (i > 0 && c >= 'A' && c <= 'Z') { + result += '_'; + } + result += ToUpper(c); + } + return result; +} + +string ExtensionMethodName(const FieldDescriptor* descriptor) { + const string& name = NameFromFieldDescriptor(descriptor); + const string& result = UnderscoresToCamelCase(name, false); + return SanitizeNameForObjC(result, "_Extension"); +} + +string FieldName(const FieldDescriptor* field) { + const string& name = NameFromFieldDescriptor(field); + string result = UnderscoresToCamelCase(name, false); + if (field->is_repeated() && !field->is_map()) { + // Add "Array" before do check for reserved worlds. + result += "Array"; + } else { + // If it wasn't repeated, but ends in "Array", force on the _p suffix. + if (HasSuffixString(result, "Array")) { + result += "_p"; + } + } + return SanitizeNameForObjC(result, "_p"); +} + +string FieldNameCapitalized(const FieldDescriptor* field) { + // Want the same suffix handling, so upcase the first letter of the other + // name. + string result = FieldName(field); + if (result.length() > 0) { + result[0] = ToUpper(result[0]); + } + return result; +} + +string OneofEnumName(const OneofDescriptor* descriptor) { + const Descriptor* fieldDescriptor = descriptor->containing_type(); + string name = ClassName(fieldDescriptor); + name += "_" + UnderscoresToCamelCase(descriptor->name(), true) + "_OneOfCase"; + // No sanitize needed because it the OS never has names that end in OneOfCase. + return name; +} + +string OneofName(const OneofDescriptor* descriptor) { + string name = UnderscoresToCamelCase(descriptor->name(), false); + // No sanitize needed because it gets OneOfCase added and that shouldn't + // ever conflict. + return name; +} + +string OneofNameCapitalized(const OneofDescriptor* descriptor) { + // Use the common handling and then up-case the first letter. + string result = OneofName(descriptor); + if (result.length() > 0) { + result[0] = ToUpper(result[0]); + } + return result; +} + +string UnCamelCaseFieldName(const string& name, const FieldDescriptor* field) { + string worker(name); + if (HasSuffixString(worker, "_p")) { + worker = StripSuffixString(worker, "_p"); + } + if (field->is_repeated() && HasSuffixString(worker, "Array")) { + worker = StripSuffixString(worker, "Array"); + } + if (field->type() == FieldDescriptor::TYPE_GROUP) { + if (worker.length() > 0) { + if (worker[0] >= 'a' && worker[0] <= 'z') { + worker[0] = ToUpper(worker[0]); + } + } + return worker; + } else { + string result; + for (int i = 0; i < worker.size(); i++) { + char c = worker[i]; + if (c >= 'A' && c <= 'Z') { + if (i > 0) { + result += '_'; + } + result += ToLower(c); + } else { + result += c; + } + } + return result; + } +} + +string GetCapitalizedType(const FieldDescriptor* field) { + switch (field->type()) { + case FieldDescriptor::TYPE_INT32: + return "Int32"; + case FieldDescriptor::TYPE_UINT32: + return "UInt32"; + case FieldDescriptor::TYPE_SINT32: + return "SInt32"; + case FieldDescriptor::TYPE_FIXED32: + return "Fixed32"; + case FieldDescriptor::TYPE_SFIXED32: + return "SFixed32"; + case FieldDescriptor::TYPE_INT64: + return "Int64"; + case FieldDescriptor::TYPE_UINT64: + return "UInt64"; + case FieldDescriptor::TYPE_SINT64: + return "SInt64"; + case FieldDescriptor::TYPE_FIXED64: + return "Fixed64"; + case FieldDescriptor::TYPE_SFIXED64: + return "SFixed64"; + case FieldDescriptor::TYPE_FLOAT: + return "Float"; + case FieldDescriptor::TYPE_DOUBLE: + return "Double"; + case FieldDescriptor::TYPE_BOOL: + return "Bool"; + case FieldDescriptor::TYPE_STRING: + return "String"; + case FieldDescriptor::TYPE_BYTES: + return "Data"; + case FieldDescriptor::TYPE_ENUM: + return "Enum"; + case FieldDescriptor::TYPE_GROUP: + return "Group"; + case FieldDescriptor::TYPE_MESSAGE: + return "Message"; + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + +ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type) { + switch (field_type) { + case FieldDescriptor::TYPE_INT32: + case FieldDescriptor::TYPE_SINT32: + case FieldDescriptor::TYPE_SFIXED32: + return OBJECTIVECTYPE_INT32; + + case FieldDescriptor::TYPE_UINT32: + case FieldDescriptor::TYPE_FIXED32: + return OBJECTIVECTYPE_UINT32; + + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_SINT64: + case FieldDescriptor::TYPE_SFIXED64: + return OBJECTIVECTYPE_INT64; + + case FieldDescriptor::TYPE_UINT64: + case FieldDescriptor::TYPE_FIXED64: + return OBJECTIVECTYPE_UINT64; + + case FieldDescriptor::TYPE_FLOAT: + return OBJECTIVECTYPE_FLOAT; + + case FieldDescriptor::TYPE_DOUBLE: + return OBJECTIVECTYPE_DOUBLE; + + case FieldDescriptor::TYPE_BOOL: + return OBJECTIVECTYPE_BOOLEAN; + + case FieldDescriptor::TYPE_STRING: + return OBJECTIVECTYPE_STRING; + + case FieldDescriptor::TYPE_BYTES: + return OBJECTIVECTYPE_DATA; + + case FieldDescriptor::TYPE_ENUM: + return OBJECTIVECTYPE_ENUM; + + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_MESSAGE: + return OBJECTIVECTYPE_MESSAGE; + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return OBJECTIVECTYPE_INT32; +} + +bool IsPrimitiveType(const FieldDescriptor* field) { + ObjectiveCType type = GetObjectiveCType(field); + switch (type) { + case OBJECTIVECTYPE_INT32: + case OBJECTIVECTYPE_UINT32: + case OBJECTIVECTYPE_INT64: + case OBJECTIVECTYPE_UINT64: + case OBJECTIVECTYPE_FLOAT: + case OBJECTIVECTYPE_DOUBLE: + case OBJECTIVECTYPE_BOOLEAN: + case OBJECTIVECTYPE_ENUM: + return true; + break; + default: + return false; + } +} + +bool IsReferenceType(const FieldDescriptor* field) { + return !IsPrimitiveType(field); +} + +static string HandleExtremeFloatingPoint(string val, bool add_float_suffix) { + if (val == "nan") { + return "NAN"; + } else if (val == "inf") { + return "INFINITY"; + } else if (val == "-inf") { + return "-INFINITY"; + } else { + // float strings with ., e or E need to have f appended + if (add_float_suffix && + (val.find(".") != string::npos || val.find("e") != string::npos || + val.find("E") != string::npos)) { + val += "f"; + } + return val; + } +} + +string GPBValueFieldName(const FieldDescriptor* field) { + // Returns the field within the GPBValue union to use for the given field. + if (field->is_repeated()) { + return "valueMessage"; + } + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + return "valueInt32"; + case FieldDescriptor::CPPTYPE_UINT32: + return "valueUInt32"; + case FieldDescriptor::CPPTYPE_INT64: + return "valueInt64"; + case FieldDescriptor::CPPTYPE_UINT64: + return "valueUInt64"; + case FieldDescriptor::CPPTYPE_FLOAT: + return "valueFloat"; + case FieldDescriptor::CPPTYPE_DOUBLE: + return "valueDouble"; + case FieldDescriptor::CPPTYPE_BOOL: + return "valueBool"; + case FieldDescriptor::CPPTYPE_STRING: + if (field->type() == FieldDescriptor::TYPE_BYTES) { + return "valueData"; + } else { + return "valueString"; + } + case FieldDescriptor::CPPTYPE_ENUM: + return "valueEnum"; + case FieldDescriptor::CPPTYPE_MESSAGE: + return "valueMessage"; + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + + +string DefaultValue(const FieldDescriptor* field) { + // Repeated fields don't have defaults. + if (field->is_repeated()) { + return "nil"; + } + + // Switch on cpp_type since we need to know which default_value_* method + // of FieldDescriptor to call. + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + // gcc and llvm reject the decimal form of kint32min and kint64min. + if (field->default_value_int32() == INT_MIN) { + return "-0x80000000"; + } + return SimpleItoa(field->default_value_int32()); + case FieldDescriptor::CPPTYPE_UINT32: + return SimpleItoa(field->default_value_uint32()) + "U"; + case FieldDescriptor::CPPTYPE_INT64: + // gcc and llvm reject the decimal form of kint32min and kint64min. + if (field->default_value_int64() == LLONG_MIN) { + return "-0x8000000000000000LL"; + } + return SimpleItoa(field->default_value_int64()) + "LL"; + case FieldDescriptor::CPPTYPE_UINT64: + return SimpleItoa(field->default_value_uint64()) + "ULL"; + case FieldDescriptor::CPPTYPE_DOUBLE: + return HandleExtremeFloatingPoint( + SimpleDtoa(field->default_value_double()), false); + case FieldDescriptor::CPPTYPE_FLOAT: + return HandleExtremeFloatingPoint( + SimpleFtoa(field->default_value_float()), true); + case FieldDescriptor::CPPTYPE_BOOL: + return field->default_value_bool() ? "YES" : "NO"; + case FieldDescriptor::CPPTYPE_STRING: { + const bool has_default_value = field->has_default_value(); + const string& default_string = field->default_value_string(); + if (!has_default_value || default_string.length() == 0) { + // If the field is defined as being the empty string, + // then we will just assign to nil, as the empty string is the + // default for both strings and data. + return "nil"; + } + if (field->type() == FieldDescriptor::TYPE_BYTES) { + // We want constant fields in our data structures so we can + // declare them as static. To achieve this we cheat and stuff + // a escaped c string (prefixed with a length) into the data + // field, and cast it to an (NSData*) so it will compile. + // The runtime library knows how to handle it. + + // Must convert to a standard byte order for packing length into + // a cstring. + uint32_t length = htonl(default_string.length()); + string bytes((const char*)&length, sizeof(length)); + bytes.append(default_string); + return "(NSData*)\"" + CEscape(bytes) + "\""; + } else { + return "@\"" + EscapeTrigraphs(CEscape(default_string)) + "\""; + } + } + case FieldDescriptor::CPPTYPE_ENUM: + return EnumValueName(field->default_value_enum()); + case FieldDescriptor::CPPTYPE_MESSAGE: + return "nil"; + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + +string BuildFlagsString(const vector<string>& strings) { + if (strings.size() == 0) { + return "0"; + } + string string; + for (size_t i = 0; i != strings.size(); ++i) { + if (i > 0) { + string.append(" | "); + } + string.append(strings[i]); + } + return string; +} + +string BuildCommentsString(const SourceLocation& location) { + const string& comments = location.leading_comments.empty() + ? location.trailing_comments + : location.leading_comments; + vector<string> lines; + SplitStringAllowEmpty(comments, "\n", &lines); + while (!lines.empty() && lines.back().empty()) { + lines.pop_back(); + } + string prefix("//"); + string suffix("\n"); + string final_comments; + for (int i = 0; i < lines.size(); i++) { + // We use $ for delimiters, so replace comments with dollars with + // html escaped version. + // None of the other compilers handle this (as of this writing) but we + // ran into it once, so just to be safe. + final_comments += + prefix + StringReplace(lines[i], "$", "$", true) + suffix; + } + return final_comments; +} + +bool WriteClassList(string* error) { + const char* file_name = getenv("GPB_CLASSLIST_PATH"); + if (file_name != NULL) { +#ifndef O_EXLOCK + int fd = open(file_name, O_WRONLY | O_APPEND | O_CREAT, + (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)); +#else + int fd = open(file_name, O_WRONLY | O_APPEND | O_EXLOCK | O_CREAT, + (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)); +#endif + if (fd == -1) { + if (error != NULL) { + stringstream err_stream; + err_stream << endl << file_name << ":0:0: error:" + << "Unable to open (" << errno << ")"; + *error = err_stream.str(); + } + return false; + } +#ifndef O_EXLOCK + if (flock(fd, LOCK_EX) < 0) { + if (error != NULL) { + stringstream err_stream; + err_stream << endl << file_name << ":0:0: error:" + << "Unable to lock (" << errno << ")"; + *error = err_stream.str(); + } + return false; + } +#endif + // Need a local to hold the list so the cstring stays valid for the + // write call. + const string& class_list_str = gClassListStream.str(); + int write_out = write(fd, class_list_str.c_str(), class_list_str.length()); + int close_out = close(fd); + if (write_out == -1 || close_out == -1) { + if (error != NULL) { + stringstream err_stream; + err_stream << endl << file_name << ":0:0: error:" + << "Unable to write (" << errno << ")"; + *error = err_stream.str(); + } + return false; + } + } + return true; +} + +void WriteClassNameToClassList(const string& name) { + if (gClassListStream.good()) { + gClassListStream << name << '\n'; + } +} + +bool InitializeClassWhitelist(string* error) { + const char* env_var_value = getenv("GPB_OBJC_CLASS_WHITELIST_PATHS"); + if (env_var_value == NULL) { + return true; + } + + // The values are joined with ';' in case we ever want to make this a + // generator parameter also (instead of env var), and generator parameter + // parsing already has meaning for ',' and ':'. + vector<string> file_paths = Split(env_var_value, ";", true); + + for (vector<string>::const_iterator i = file_paths.begin(); + i != file_paths.end(); ++i) { + const string& file_path = *i; + + ifstream stream(file_path.c_str(), ifstream::in); + if (!stream.good()) { + if (error != NULL) { + stringstream err_stream; + err_stream << endl << file_path << ":0:0: error: Unable to open"; + *error = err_stream.str(); + return false; + } + } + + string input_line; + while (stream.good()) { + getline(stream, input_line); + string trimmed_line(TrimString(input_line)); + if (trimmed_line.length() == 0) { + // Skip empty lines + continue; + } + if (trimmed_line[0] == '/' || trimmed_line[0] == '#') { + // Skip comments and potential preprocessor symbols + continue; + } + gClassWhitelist.insert(trimmed_line); + } + } + return true; +} + +bool FilterClass(const string& name) { + if (gClassWhitelist.count(name) > 0) { + // Whitelisted, don't filter. + return false; + } + + // If there was no list, default to everything in. + // If there was a list, default to everything out. + return gClassWhitelist.size() > 0; +} + +void TextFormatDecodeData::AddString(int32_t key, + const string& input_for_decode, + const string& desired_output) { + for (vector<DataEntry>::const_iterator i = entries_.begin(); + i != entries_.end(); ++i) { + if (i->first == key) { + cerr << "error: duplicate key (" << key + << ") making TextFormat data, input: \"" << input_for_decode + << "\", desired: \"" << desired_output << "\"." << endl; + cerr.flush(); + abort(); + } + } + + const string& data = TextFormatDecodeData::DecodeDataForString( + input_for_decode, desired_output); + entries_.push_back(DataEntry(key, data)); +} + +string TextFormatDecodeData::Data() const { + ostringstream data_stringstream; + + if (num_entries() > 0) { + io::OstreamOutputStream data_outputstream(&data_stringstream); + io::CodedOutputStream output_stream(&data_outputstream); + + output_stream.WriteVarint32(num_entries()); + for (vector<DataEntry>::const_iterator i = entries_.begin(); + i != entries_.end(); ++i) { + output_stream.WriteVarint32(i->first); + output_stream.WriteString(i->second); + } + } + + data_stringstream.flush(); + return data_stringstream.str(); +} + +namespace { + +// Helper to build up the decode data for a string. +class DecodeDataBuilder { + public: + DecodeDataBuilder() { Reset(); } + + bool AddCharacter(const char desired, const char input); + void AddUnderscore() { + Push(); + need_underscore_ = true; + } + string Finish() { + Push(); + return decode_data_; + } + + private: + static const uint8_t kAddUnderscore = 0b10000000; + + static const uint8_t kOpAsIs = 0b00000000; + static const uint8_t kOpFirstUpper = 0b01000000; + static const uint8_t kOpFirstLower = 0b00100000; + static const uint8_t kOpAllUpper = 0b01100000; + + static const int kMaxSegmentLen = 0b00011111; + + void AddChar(const char desired) { + ++segment_len_; + is_all_upper_ &= IsUpper(desired); + } + + void Push() { + uint8_t op = (op_ | segment_len_); + if (need_underscore_) op |= kAddUnderscore; + if (op != 0) { + decode_data_ += (char)op; + } + Reset(); + } + + bool AddFirst(const char desired, const char input) { + if (desired == input) { + op_ = kOpAsIs; + } else if (desired == ToUpper(input)) { + op_ = kOpFirstUpper; + } else if (desired == ToLower(input)) { + op_ = kOpFirstLower; + } else { + // Can't be transformed to match. + return false; + } + AddChar(desired); + return true; + } + + void Reset() { + need_underscore_ = false; + op_ = 0; + segment_len_ = 0; + is_all_upper_ = true; + } + + bool need_underscore_; + bool is_all_upper_; + uint8_t op_; + int segment_len_; + + string decode_data_; +}; + +bool DecodeDataBuilder::AddCharacter(const char desired, const char input) { + // If we've hit the max size, push to start a new segment. + if (segment_len_ == kMaxSegmentLen) { + Push(); + } + if (segment_len_ == 0) { + return AddFirst(desired, input); + } + + // Desired and input match... + if (desired == input) { + // If we aren't transforming it, or we're upper casing it and it is + // supposed to be uppercase; just add it to the segment. + if ((op_ != kOpAllUpper) || IsUpper(desired)) { + AddChar(desired); + return true; + } + + // Add the current segment, and start the next one. + Push(); + return AddFirst(desired, input); + } + + // If we need to uppercase, and everything so far has been uppercase, + // promote op to AllUpper. + if ((desired == ToUpper(input)) && is_all_upper_) { + op_ = kOpAllUpper; + AddChar(desired); + return true; + } + + // Give up, push and start a new segment. + Push(); + return AddFirst(desired, input); +} + +// If decode data can't be generated, a directive for the raw string +// is used instead. +string DirectDecodeString(const string& str) { + string result; + result += (char)'\0'; // Marker for full string. + result += str; + result += (char)'\0'; // End of string. + return result; +} + +} // namespace + +// static +string TextFormatDecodeData::DecodeDataForString(const string& input_for_decode, + const string& desired_output) { + if ((input_for_decode.size() == 0) || (desired_output.size() == 0)) { + cerr << "error: got empty string for making TextFormat data, input: \"" + << input_for_decode << "\", desired: \"" << desired_output << "\"." + << endl; + cerr.flush(); + abort(); + } + if ((input_for_decode.find('\0') != string::npos) || + (desired_output.find('\0') != string::npos)) { + cerr << "error: got a null char in a string for making TextFormat data," + << " input: \"" << CEscape(input_for_decode) << "\", desired: \"" + << CEscape(desired_output) << "\"." << endl; + cerr.flush(); + abort(); + } + + DecodeDataBuilder builder; + + // Walk the output building it from the input. + int x = 0; + for (int y = 0; y < desired_output.size(); y++) { + const char d = desired_output[y]; + if (d == '_') { + builder.AddUnderscore(); + continue; + } + + if (x >= input_for_decode.size()) { + // Out of input, no way to encode it, just return a full decode. + return DirectDecodeString(desired_output); + } + if (builder.AddCharacter(d, input_for_decode[x])) { + ++x; // Consumed one input + } else { + // Couldn't transform for the next character, just return a full decode. + return DirectDecodeString(desired_output); + } + } + + if (x != input_for_decode.size()) { + // Extra input (suffix from name sanitizing?), just return a full decode. + return DirectDecodeString(desired_output); + } + + // Add the end marker. + return builder.Finish() + (char)'\0'; +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h new file mode 100644 index 00000000..2701a30c --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h @@ -0,0 +1,176 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__ + +#include <string> +#include <vector> + +#include <google/protobuf/descriptor.h> +#include <google/protobuf/descriptor.pb.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +// Strips ".proto" or ".protodevel" from the end of a filename. +string StripProto(const string& filename); + +// Returns true if the name requires a ns_returns_not_retained attribute applied +// to it. +bool IsRetainedName(const string& name); + +// Returns true if the name starts with "init" and will need to have special +// handling under ARC. +bool IsInitName(const string& name); + +// Gets the name of the file we're going to generate (sans the .pb.h +// extension). This does not include the path to that file. +string FileName(const FileDescriptor* file); + +// Gets the path of the file we're going to generate (sans the .pb.h +// extension). The path will be dependent on the objectivec package +// declared in the proto package. +string FilePath(const FileDescriptor* file); + +// Gets the name of the root class we'll generate in the file. This class +// is not meant for external consumption, but instead contains helpers that +// the rest of the the classes need +string FileClassName(const FileDescriptor* file); + +// These return the fully-qualified class name corresponding to the given +// descriptor. +string ClassName(const Descriptor* descriptor); +string EnumName(const EnumDescriptor* descriptor); + +// Returns the fully-qualified name of the enum value corresponding to the +// the descriptor. +string EnumValueName(const EnumValueDescriptor* descriptor); + +// Returns the name of the enum value corresponding to the descriptor. +string EnumValueShortName(const EnumValueDescriptor* descriptor); + +// Reverse what an enum does. +string UnCamelCaseEnumShortName(const string& name); + +// Returns the name to use for the extension (used as the method off the file's +// Root class). +string ExtensionMethodName(const FieldDescriptor* descriptor); + +// Returns the transformed field name. +string FieldName(const FieldDescriptor* field); +string FieldNameCapitalized(const FieldDescriptor* field); + +// Returns the transformed oneof name. +string OneofEnumName(const OneofDescriptor* descriptor); +string OneofName(const OneofDescriptor* descriptor); +string OneofNameCapitalized(const OneofDescriptor* descriptor); + +inline bool HasFieldPresence(const FileDescriptor* file) { + return file->syntax() != FileDescriptor::SYNTAX_PROTO3; +} + +inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) { + return file->syntax() == FileDescriptor::SYNTAX_PROTO3; +} + +inline bool IsMapEntryMessage(const Descriptor* descriptor) { + return descriptor->options().map_entry(); +} + +// Reverse of the above. +string UnCamelCaseFieldName(const string& name, const FieldDescriptor* field); + +enum ObjectiveCType { + OBJECTIVECTYPE_INT32, + OBJECTIVECTYPE_UINT32, + OBJECTIVECTYPE_INT64, + OBJECTIVECTYPE_UINT64, + OBJECTIVECTYPE_FLOAT, + OBJECTIVECTYPE_DOUBLE, + OBJECTIVECTYPE_BOOLEAN, + OBJECTIVECTYPE_STRING, + OBJECTIVECTYPE_DATA, + OBJECTIVECTYPE_ENUM, + OBJECTIVECTYPE_MESSAGE +}; + +string GetCapitalizedType(const FieldDescriptor* field); + +ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type); + +inline ObjectiveCType GetObjectiveCType(const FieldDescriptor* field) { + return GetObjectiveCType(field->type()); +} + +bool IsPrimitiveType(const FieldDescriptor* field); +bool IsReferenceType(const FieldDescriptor* field); + +string GPBValueFieldName(const FieldDescriptor* field); +string DefaultValue(const FieldDescriptor* field); + +string BuildFlagsString(const vector<string>& strings); + +string BuildCommentsString(const SourceLocation& location); + +bool WriteClassList(string* error); +void WriteClassNameToClassList(const string& name); + +bool InitializeClassWhitelist(string* error); +bool FilterClass(const string& name); + +// Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform +// the input into the the expected output. +class TextFormatDecodeData { + public: + TextFormatDecodeData() {} + + void AddString(int32_t key, const string& input_for_decode, + const string& desired_output); + size_t num_entries() const { return entries_.size(); } + string Data() const; + + static string DecodeDataForString(const string& input_for_decode, + const string& desired_output); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextFormatDecodeData); + + typedef std::pair<int32_t, string> DataEntry; + vector<DataEntry> entries_; +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc new file mode 100644 index 00000000..c9682b08 --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc @@ -0,0 +1,242 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2014 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> +#include <google/protobuf/testing/googletest.h> +#include <gtest/gtest.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { +namespace { + +TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_RawStrings) { + string input_for_decode("abcdefghIJ"); + string desired_output_for_decode; + string expected; + string result; + + // Different data, can't transform. + + desired_output_for_decode = "zbcdefghIJ"; + expected = string("\0zbcdefghIJ\0", 12); + result = TextFormatDecodeData::DecodeDataForString(input_for_decode, + desired_output_for_decode); + EXPECT_EQ(expected, result); + + desired_output_for_decode = "abcdezghIJ"; + expected = string("\0abcdezghIJ\0", 12); + result = TextFormatDecodeData::DecodeDataForString(input_for_decode, + desired_output_for_decode); + EXPECT_EQ(expected, result); + + // Shortened data, can't transform. + + desired_output_for_decode = "abcdefghI"; + expected = string("\0abcdefghI\0", 11); + result = TextFormatDecodeData::DecodeDataForString(input_for_decode, + desired_output_for_decode); + EXPECT_EQ(expected, result); + + // Extra data, can't transform. + + desired_output_for_decode = "abcdefghIJz"; + expected = string("\0abcdefghIJz\0", 13); + result = TextFormatDecodeData::DecodeDataForString(input_for_decode, + desired_output_for_decode); + EXPECT_EQ(expected, result); +} + +TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_ByteCodes) { + string input_for_decode("abcdefghIJ"); + string desired_output_for_decode; + string expected; + string result; + + desired_output_for_decode = "abcdefghIJ"; + expected = string("\x0A\x0", 2); + result = TextFormatDecodeData::DecodeDataForString(input_for_decode, + desired_output_for_decode); + EXPECT_EQ(expected, result); + + desired_output_for_decode = "_AbcdefghIJ"; + expected = string("\xCA\x0", 2); + result = TextFormatDecodeData::DecodeDataForString(input_for_decode, + desired_output_for_decode); + EXPECT_EQ(expected, result); + + desired_output_for_decode = "ABCD__EfghI_j"; + expected = string("\x64\x80\xC5\xA1\x0", 5); + result = TextFormatDecodeData::DecodeDataForString(input_for_decode, + desired_output_for_decode); + EXPECT_EQ(expected, result); + + // Long name so multiple decode ops are needed. + + input_for_decode = + "longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000"; + desired_output_for_decode = + "long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000"; + expected = string("\x04\xA5\xA4\xA2\xBF\x1F\x0E\x84\x0", 9); + result = TextFormatDecodeData::DecodeDataForString(input_for_decode, + desired_output_for_decode); + EXPECT_EQ(expected, result); +} + +TEST(ObjCHelperDeathTest, TextFormatDecodeData_DecodeDataForString_Failures) { + // Empty inputs. + + EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("", ""), + ::testing::KilledBySignal(SIGABRT), + "error: got empty string for making TextFormat data, input:"); + EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("a", ""), + ::testing::KilledBySignal(SIGABRT), + "error: got empty string for making TextFormat data, input:"); + EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("", "a"), + ::testing::KilledBySignal(SIGABRT), + "error: got empty string for making TextFormat data, input:"); + + // Null char in the string. + + string str_with_null_char("ab\0c", 4); + EXPECT_EXIT( + TextFormatDecodeData::DecodeDataForString(str_with_null_char, "def"), + ::testing::KilledBySignal(SIGABRT), + "error: got a null char in a string for making TextFormat data, input:"); + EXPECT_EXIT( + TextFormatDecodeData::DecodeDataForString("def", str_with_null_char), + ::testing::KilledBySignal(SIGABRT), + "error: got a null char in a string for making TextFormat data, input:"); +} + +TEST(ObjCHelper, TextFormatDecodeData_RawStrings) { + TextFormatDecodeData decode_data; + + // Different data, can't transform. + decode_data.AddString(1, "abcdefghIJ", "zbcdefghIJ"); + decode_data.AddString(3, "abcdefghIJ", "abcdezghIJ"); + // Shortened data, can't transform. + decode_data.AddString(2, "abcdefghIJ", "abcdefghI"); + // Extra data, can't transform. + decode_data.AddString(4, "abcdefghIJ", "abcdefghIJz"); + + EXPECT_EQ(4, decode_data.num_entries()); + + uint8_t expected_data[] = { + 0x4, + 0x1, 0x0, 'z', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 0x0, + 0x3, 0x0, 'a', 'b', 'c', 'd', 'e', 'z', 'g', 'h', 'I', 'J', 0x0, + 0x2, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 0x0, + 0x4, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 'z', 0x0, + }; + string expected((const char*)expected_data, sizeof(expected_data)); + + EXPECT_EQ(expected, decode_data.Data()); +} + +TEST(ObjCHelper, TextFormatDecodeData_ByteCodes) { + TextFormatDecodeData decode_data; + + decode_data.AddString(1, "abcdefghIJ", "abcdefghIJ"); + decode_data.AddString(3, "abcdefghIJ", "_AbcdefghIJ"); + decode_data.AddString(2, "abcdefghIJ", "Abcd_EfghIJ"); + decode_data.AddString(4, "abcdefghIJ", "ABCD__EfghI_j"); + decode_data.AddString(1000, + "longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000", + "long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000"); + + EXPECT_EQ(5, decode_data.num_entries()); + + uint8_t expected_data[] = { + 0x5, + // All as is (00 op) + 0x1, 0x0A, 0x0, + // Underscore, upper + 9 (10 op) + 0x3, 0xCA, 0x0, + // Upper + 3 (10 op), underscore, upper + 5 (10 op) + 0x2, 0x44, 0xC6, 0x0, + // All Upper for 4 (11 op), underscore, underscore, upper + 5 (10 op), + // underscore, lower + 0 (01 op) + 0x4, 0x64, 0x80, 0xC5, 0xA1, 0x0, + // 2 byte key: as is + 3 (00 op), underscore, lower + 4 (01 op), + // underscore, lower + 3 (01 op), underscore, lower + 1 (01 op), + // underscore, lower + 30 (01 op), as is + 30 (00 op), as is + 13 (00 + // op), + // underscore, as is + 3 (00 op) + 0xE8, 0x07, 0x04, 0xA5, 0xA4, 0xA2, 0xBF, 0x1F, 0x0E, 0x84, 0x0, + }; + string expected((const char*)expected_data, sizeof(expected_data)); + + EXPECT_EQ(expected, decode_data.Data()); +} + +TEST(ObjCHelperDeathTest, TextFormatDecodeData_Failures) { + TextFormatDecodeData decode_data; + + // Empty inputs. + + EXPECT_EXIT(decode_data.AddString(1, "", ""), + ::testing::KilledBySignal(SIGABRT), + "error: got empty string for making TextFormat data, input:"); + EXPECT_EXIT(decode_data.AddString(1, "a", ""), + ::testing::KilledBySignal(SIGABRT), + "error: got empty string for making TextFormat data, input:"); + EXPECT_EXIT(decode_data.AddString(1, "", "a"), + ::testing::KilledBySignal(SIGABRT), + "error: got empty string for making TextFormat data, input:"); + + // Null char in the string. + + string str_with_null_char("ab\0c", 4); + EXPECT_EXIT( + decode_data.AddString(1, str_with_null_char, "def"), + ::testing::KilledBySignal(SIGABRT), + "error: got a null char in a string for making TextFormat data, input:"); + EXPECT_EXIT( + decode_data.AddString(1, "def", str_with_null_char), + ::testing::KilledBySignal(SIGABRT), + "error: got a null char in a string for making TextFormat data, input:"); + + // Duplicate keys + + decode_data.AddString(1, "abcdefghIJ", "abcdefghIJ"); + decode_data.AddString(3, "abcdefghIJ", "_AbcdefghIJ"); + decode_data.AddString(2, "abcdefghIJ", "Abcd_EfghIJ"); + EXPECT_EXIT(decode_data.AddString(2, "xyz", "x_yz"), + ::testing::KilledBySignal(SIGABRT), + "error: duplicate key \\(2\\) making TextFormat data, input:"); +} + +} // namespace +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc new file mode 100644 index 00000000..cafdf39d --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc @@ -0,0 +1,161 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <map> +#include <string> + +#include <google/protobuf/compiler/objectivec/objectivec_map_field.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/substitute.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +// MapFieldGenerator uses RepeatedFieldGenerator as the parent because it +// provides a bunch of things (no has* methods, comments for contained type, +// etc.). + +namespace { + +const char* MapEntryTypeName(const FieldDescriptor* descriptor, bool isKey) { + ObjectiveCType type = GetObjectiveCType(descriptor); + switch (type) { + case OBJECTIVECTYPE_INT32: + return "Int32"; + case OBJECTIVECTYPE_UINT32: + return "UInt32"; + case OBJECTIVECTYPE_INT64: + return "Int64"; + case OBJECTIVECTYPE_UINT64: + return "UInt64"; + case OBJECTIVECTYPE_FLOAT: + return "Float"; + case OBJECTIVECTYPE_DOUBLE: + return "Double"; + case OBJECTIVECTYPE_BOOLEAN: + return "Bool"; + case OBJECTIVECTYPE_STRING: + return (isKey ? "String" : "Object"); + case OBJECTIVECTYPE_DATA: + return "Object"; + case OBJECTIVECTYPE_ENUM: + return "Enum"; + case OBJECTIVECTYPE_MESSAGE: + return "Object"; + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + +} // namespace + +MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor) + : RepeatedFieldGenerator(descriptor) { + const FieldDescriptor* key_descriptor = + descriptor->message_type()->FindFieldByName("key"); + const FieldDescriptor* value_descriptor = + descriptor->message_type()->FindFieldByName("value"); + value_field_generator_.reset(FieldGenerator::Make(value_descriptor)); + + // Pull over some variables_ from the value. + variables_["field_type"] = value_field_generator_->variable("field_type"); + variables_["default"] = value_field_generator_->variable("default"); + variables_["default_name"] = value_field_generator_->variable("default_name"); + + // Build custom field flags. + std::vector<string> field_flags; + field_flags.push_back("GPBFieldMapKey" + GetCapitalizedType(key_descriptor)); + // Pull over the current text format custom name values that was calculated. + if (variables_["fieldflags"].find("GPBFieldTextFormatNameCustom") != + string::npos) { + field_flags.push_back("GPBFieldTextFormatNameCustom"); + } + // Pull over some info from the value's flags. + const string& value_field_flags = + value_field_generator_->variable("fieldflags"); + if (value_field_flags.find("GPBFieldHasDefaultValue") != string::npos) { + field_flags.push_back("GPBFieldHasDefaultValue"); + } + if (value_field_flags.find("GPBFieldHasEnumDescriptor") != string::npos) { + field_flags.push_back("GPBFieldHasEnumDescriptor"); + } + variables_["fieldflags"] = BuildFlagsString(field_flags); + + ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor); + if ((GetObjectiveCType(key_descriptor) == OBJECTIVECTYPE_STRING) && + ((value_objc_type == OBJECTIVECTYPE_STRING) || + (value_objc_type == OBJECTIVECTYPE_DATA) || + (value_objc_type == OBJECTIVECTYPE_MESSAGE))) { + variables_["array_storage_type"] = "NSMutableDictionary"; + } else { + string base_name = MapEntryTypeName(key_descriptor, true); + base_name += MapEntryTypeName(value_descriptor, false); + base_name += "Dictionary"; + variables_["array_storage_type"] = "GPB" + base_name; + } +} + +MapFieldGenerator::~MapFieldGenerator() {} + +void MapFieldGenerator::FinishInitialization(void) { + RepeatedFieldGenerator::FinishInitialization(); + // Use the array_comment suport in RepeatedFieldGenerator to output what the + // values in the map are. + const FieldDescriptor* value_descriptor = + descriptor_->message_type()->FindFieldByName("value"); + ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor); + if ((value_objc_type == OBJECTIVECTYPE_MESSAGE) || + (value_objc_type == OBJECTIVECTYPE_DATA) || + (value_objc_type == OBJECTIVECTYPE_STRING) || + (value_objc_type == OBJECTIVECTYPE_ENUM)) { + variables_["array_comment"] = + "// |" + variables_["name"] + "| values are |" + value_field_generator_->variable("storage_type") + "|\n"; + } else { + variables_["array_comment"] = ""; + } +} + +void MapFieldGenerator::GenerateFieldDescriptionTypeSpecific( + io::Printer* printer) const { + // Relay it to the value generator to provide enum validator, message + // class, etc. + value_field_generator_->GenerateFieldDescriptionTypeSpecific(printer); +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h new file mode 100644 index 00000000..8862dc35 --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h @@ -0,0 +1,64 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__ + +#include <map> +#include <string> +#include <google/protobuf/compiler/objectivec/objectivec_field.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +class MapFieldGenerator : public RepeatedFieldGenerator { + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); + + public: + virtual void FinishInitialization(void); + virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const; + + protected: + MapFieldGenerator(const FieldDescriptor* descriptor); + virtual ~MapFieldGenerator(); + + private: + scoped_ptr<FieldGenerator> value_field_generator_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator); +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc new file mode 100644 index 00000000..87e4d0f8 --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc @@ -0,0 +1,642 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <algorithm> +#include <iostream> +#include <sstream> + +#include <google/protobuf/stubs/hash.h> +#include <google/protobuf/compiler/objectivec/objectivec_message.h> +#include <google/protobuf/compiler/objectivec/objectivec_enum.h> +#include <google/protobuf/compiler/objectivec/objectivec_extension.h> +#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> +#include <google/protobuf/stubs/stl_util.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/wire_format.h> +#include <google/protobuf/wire_format_lite_inl.h> +#include <google/protobuf/descriptor.pb.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +using internal::WireFormat; +using internal::WireFormatLite; + +namespace { +struct FieldOrderingByNumber { + inline bool operator()(const FieldDescriptor* a, + const FieldDescriptor* b) const { + return a->number() < b->number(); + } +}; + +int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) { + // The first item in the object structure is our uint32[] for has bits. + // We then want to order things to make the instances as small as + // possible. So we follow the has bits with: + // 1. Bools (1 byte) + // 2. Anything always 4 bytes - float, *32, enums + // 3. Anything that is always a pointer (they will be 8 bytes on 64 bit + // builds and 4 bytes on 32bit builds. + // 4. Anything always 8 bytes - double, *64 + // + // Why? Using 64bit builds as an example, this means worse case, we have + // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes + // are wasted before the 4 byte values. Then if we have an odd number of + // those 4 byte values, the 8 byte values will be pushed down by 32bits to + // keep them aligned. But the structure will end 8 byte aligned, so no + // waste on the end. If you did the reverse order, you could waste 4 bytes + // before the first 8 byte value (after the has array), then a single + // bool on the end would need 7 bytes of padding to make the overall + // structure 8 byte aligned; so 11 bytes, wasted total. + + // Anything repeated is a GPB*Array/NSArray, so pointer. + if (descriptor->is_repeated()) { + return 3; + } + + switch (descriptor->type()) { + // All always 8 bytes. + case FieldDescriptor::TYPE_DOUBLE: + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_SINT64: + case FieldDescriptor::TYPE_UINT64: + case FieldDescriptor::TYPE_SFIXED64: + case FieldDescriptor::TYPE_FIXED64: + return 4; + + // Pointers (string and bytes are NSString and NSData); 8 or 4 bytes + // depending on the build architecture. + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_MESSAGE: + case FieldDescriptor::TYPE_STRING: + case FieldDescriptor::TYPE_BYTES: + return 3; + + // All always 4 bytes (enums are int32s). + case FieldDescriptor::TYPE_FLOAT: + case FieldDescriptor::TYPE_INT32: + case FieldDescriptor::TYPE_SINT32: + case FieldDescriptor::TYPE_UINT32: + case FieldDescriptor::TYPE_SFIXED32: + case FieldDescriptor::TYPE_FIXED32: + case FieldDescriptor::TYPE_ENUM: + return 2; + + // 1 byte. + case FieldDescriptor::TYPE_BOOL: + return 1; + } +} + +struct FieldOrderingByStorageSize { + inline bool operator()(const FieldDescriptor* a, + const FieldDescriptor* b) const { + // Order by grouping. + const int order_group_a = OrderGroupForFieldDescriptor(a); + const int order_group_b = OrderGroupForFieldDescriptor(b); + if (order_group_a != order_group_b) { + return order_group_a < order_group_b; + } + // Within the group, order by field number (provides stable ordering). + return a->number() < b->number(); + } +}; + +struct ExtensionRangeOrdering { + bool operator()(const Descriptor::ExtensionRange* a, + const Descriptor::ExtensionRange* b) const { + return a->start < b->start; + } +}; + +// Sort the fields of the given Descriptor by number into a new[]'d array +// and return it. +const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { + const FieldDescriptor** fields = + new const FieldDescriptor* [descriptor->field_count()]; + for (int i = 0; i < descriptor->field_count(); i++) { + fields[i] = descriptor->field(i); + } + sort(fields, fields + descriptor->field_count(), FieldOrderingByNumber()); + return fields; +} + +// Sort the fields of the given Descriptor by storage size into a new[]'d +// array and return it. +const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) { + const FieldDescriptor** fields = + new const FieldDescriptor* [descriptor->field_count()]; + for (int i = 0; i < descriptor->field_count(); i++) { + fields[i] = descriptor->field(i); + } + sort(fields, fields + descriptor->field_count(), + FieldOrderingByStorageSize()); + return fields; +} +} // namespace + +MessageGenerator::MessageGenerator(const string& root_classname, + const Descriptor* descriptor) + : root_classname_(root_classname), + descriptor_(descriptor), + field_generators_(descriptor), + class_name_(ClassName(descriptor_)), + sub_content_filtered_(true) { + if (FilterClass(class_name_)) { + filter_reason_ = + string("Message |") + class_name_ + "| was not whitelisted."; + } + if (!IsFiltered()) { + // No need to generate extensions if this message is filtered + for (int i = 0; i < descriptor_->extension_count(); i++) { + extension_generators_.push_back( + new ExtensionGenerator(class_name_, descriptor_->extension(i))); + } + // No need to oneofs if this message is filtered + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i)); + oneof_generators_.push_back(generator); + } + } + + // We may have enums of this message that are used even if the message + // itself is filtered. + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i)); + // The enums are exposed via C functions, so they will dead strip if + // not used. + sub_content_filtered_ &= false; + enum_generators_.push_back(generator); + } + + // We may have nested messages that are used even if the message itself + // is filtered. + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + const Descriptor* nested_descriptor = descriptor_->nested_type(i); + MessageGenerator* generator = + new MessageGenerator(root_classname_, nested_descriptor); + // Don't check map entries for being filtered, as they don't directly + // generate anything in Objective C. In theory, they only should include + // references to other toplevel types, but we still make the generators + // to be safe. + if (!IsMapEntryMessage(nested_descriptor)) { + sub_content_filtered_ &= generator->IsFiltered(); + } + sub_content_filtered_ &= generator->IsSubContentFiltered(); + nested_message_generators_.push_back(generator); + } +} + +MessageGenerator::~MessageGenerator() { + STLDeleteContainerPointers(extension_generators_.begin(), + extension_generators_.end()); + STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end()); + STLDeleteContainerPointers(nested_message_generators_.begin(), + nested_message_generators_.end()); + STLDeleteContainerPointers(oneof_generators_.begin(), + oneof_generators_.end()); +} + +void MessageGenerator::GenerateStaticVariablesInitialization( + io::Printer* printer, bool* out_generated) { + if (!IsFiltered()) { + // Skip extensions if we are filtered. + for (vector<ExtensionGenerator*>::iterator iter = + extension_generators_.begin(); + iter != extension_generators_.end(); ++iter) { + (*iter)->GenerateStaticVariablesInitialization(printer, out_generated, + false); + } + } + + // Generating sub messages is perfectly fine though. + for (vector<MessageGenerator*>::iterator iter = + nested_message_generators_.begin(); + iter != nested_message_generators_.end(); ++iter) { + (*iter)->GenerateStaticVariablesInitialization(printer, out_generated); + } +} + +void MessageGenerator::DetermineDependencies(set<string>* dependencies) { + if (!IsFiltered() && !IsMapEntryMessage(descriptor_)) { + dependencies->insert("@class " + class_name_); + } + + for (vector<MessageGenerator*>::iterator iter = + nested_message_generators_.begin(); + iter != nested_message_generators_.end(); ++iter) { + (*iter)->DetermineDependencies(dependencies); + } +} + +void MessageGenerator::GenerateEnumHeader(io::Printer* printer) { + for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin(); + iter != enum_generators_.end(); ++iter) { + (*iter)->GenerateHeader(printer); + } + + for (vector<MessageGenerator*>::iterator iter = + nested_message_generators_.begin(); + iter != nested_message_generators_.end(); ++iter) { + (*iter)->GenerateEnumHeader(printer); + } +} + +void MessageGenerator::GenerateExtensionRegistrationSource( + io::Printer* printer) { + if (!IsFiltered()) { + for (vector<ExtensionGenerator*>::iterator iter = + extension_generators_.begin(); + iter != extension_generators_.end(); ++iter) { + (*iter)->GenerateRegistrationSource(printer); + } + } + + for (vector<MessageGenerator*>::iterator iter = + nested_message_generators_.begin(); + iter != nested_message_generators_.end(); ++iter) { + (*iter)->GenerateExtensionRegistrationSource(printer); + } +} + +void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { + // This a a map entry message, just recurse and do nothing directly. + if (IsMapEntryMessage(descriptor_)) { + for (vector<MessageGenerator*>::iterator iter = + nested_message_generators_.begin(); + iter != nested_message_generators_.end(); ++iter) { + (*iter)->GenerateMessageHeader(printer); + } + return; + } + + WriteClassNameToClassList(class_name_); + + if (IsFiltered()) { + printer->Print("// $filter_reason$\n\n", + "filter_reason", filter_reason_); + } else { + printer->Print( + "#pragma mark - $classname$\n" + "\n", + "classname", class_name_); + + if (descriptor_->field_count()) { + // Even if there are fields, they could be filtered away, so always use + // a buffer to confirm we have something. + ostringstream fieldnumber_stringstream; + { + scoped_array<const FieldDescriptor*> sorted_fields( + SortFieldsByNumber(descriptor_)); + + io::OstreamOutputStream fieldnumber_outputstream( + &fieldnumber_stringstream); + io::Printer fieldnumber_printer(&fieldnumber_outputstream, '$'); + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(sorted_fields[i]) + .GenerateFieldNumberConstant(&fieldnumber_printer); + } + fieldnumber_stringstream.flush(); + } + const string& fieldnumber_str = fieldnumber_stringstream.str(); + if (fieldnumber_str.length()) { + printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n", + "classname", class_name_); + printer->Indent(); + printer->Print(fieldnumber_str.c_str()); + printer->Outdent(); + printer->Print("};\n\n"); + } + } + + for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin(); + iter != oneof_generators_.end(); ++iter) { + (*iter)->GenerateCaseEnum(printer); + } + + string message_comments; + SourceLocation location; + if (descriptor_->GetSourceLocation(&location)) { + message_comments = BuildCommentsString(location); + } else { + message_comments = ""; + } + + printer->Print( + "$comments$@interface $classname$ : GPBMessage\n\n", + "classname", class_name_, + "comments", message_comments); + + vector<bool> seen_oneofs(descriptor_->oneof_decl_count(), false); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (field->containing_oneof() != NULL) { + const int oneof_index = field->containing_oneof()->index(); + if (!seen_oneofs[oneof_index]) { + seen_oneofs[oneof_index] = true; + oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration( + printer); + } + } + field_generators_.get(field) + .GeneratePropertyDeclaration(printer); + } + + printer->Print("@end\n\n"); + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateCFunctionDeclarations(printer); + } + + if (!oneof_generators_.empty()) { + for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin(); + iter != oneof_generators_.end(); ++iter) { + (*iter)->GenerateClearFunctionDeclaration(printer); + } + printer->Print("\n"); + } + + if (descriptor_->extension_count() > 0) { + printer->Print("@interface $classname$ (DynamicMethods)\n\n", + "classname", class_name_); + for (vector<ExtensionGenerator*>::iterator iter = + extension_generators_.begin(); + iter != extension_generators_.end(); ++iter) { + (*iter)->GenerateMembersHeader(printer); + } + printer->Print("@end\n\n"); + } + } + + for (vector<MessageGenerator*>::iterator iter = + nested_message_generators_.begin(); + iter != nested_message_generators_.end(); ++iter) { + (*iter)->GenerateMessageHeader(printer); + } +} + +void MessageGenerator::GenerateSource(io::Printer* printer) { + if (!IsFiltered() && !IsMapEntryMessage(descriptor_)) { + printer->Print( + "#pragma mark - $classname$\n" + "\n", + "classname", class_name_); + + printer->Print("@implementation $classname$\n\n", + "classname", class_name_); + + for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin(); + iter != oneof_generators_.end(); ++iter) { + (*iter)->GeneratePropertyImplementation(printer); + } + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GeneratePropertyImplementation(printer); + } + + scoped_array<const FieldDescriptor*> sorted_fields( + SortFieldsByNumber(descriptor_)); + scoped_array<const FieldDescriptor*> size_order_fields( + SortFieldsByStorageSize(descriptor_)); + + vector<const Descriptor::ExtensionRange*> sorted_extensions; + for (int i = 0; i < descriptor_->extension_range_count(); ++i) { + sorted_extensions.push_back(descriptor_->extension_range(i)); + } + + sort(sorted_extensions.begin(), sorted_extensions.end(), + ExtensionRangeOrdering()); + + size_t num_has_bits = descriptor_->field_count(); + size_t sizeof_has_storage = (num_has_bits + 31) / 32; + // Tell all the fields the oneof base. + for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin(); + iter != oneof_generators_.end(); ++iter) { + (*iter)->SetOneofIndexBase(sizeof_has_storage); + } + field_generators_.SetOneofIndexBase(sizeof_has_storage); + // Add an int32 for each oneof to store which is set. + sizeof_has_storage += descriptor_->oneof_decl_count(); + + printer->Print( + "\n" + "typedef struct $classname$_Storage {\n" + " uint32_t _has_storage_[$sizeof_has_storage$];\n", + "classname", class_name_, + "sizeof_has_storage", SimpleItoa(sizeof_has_storage)); + printer->Indent(); + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(size_order_fields[i]) + .GenerateFieldStorageDeclaration(printer); + } + printer->Outdent(); + + printer->Print("} $classname$_Storage;\n\n", "classname", class_name_); + + + printer->Print( + "// This method is threadsafe because it is initially called\n" + "// in +initialize for each subclass.\n" + "+ (GPBDescriptor *)descriptor {\n" + " static GPBDescriptor *descriptor = NULL;\n" + " if (!descriptor) {\n"); + + bool has_oneofs = oneof_generators_.size(); + if (has_oneofs) { + printer->Print( + " static GPBMessageOneofDescription oneofs[] = {\n"); + printer->Indent(); + printer->Indent(); + printer->Indent(); + for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin(); + iter != oneof_generators_.end(); ++iter) { + (*iter)->GenerateDescription(printer); + } + printer->Outdent(); + printer->Outdent(); + printer->Outdent(); + printer->Print( + " };\n"); + } + + printer->Print( + " static GPBMessageFieldDescription fields[] = {\n"); + printer->Indent(); + printer->Indent(); + printer->Indent(); + TextFormatDecodeData text_format_decode_data; + for (int i = 0; i < descriptor_->field_count(); ++i) { + const FieldGenerator& field_generator = + field_generators_.get(sorted_fields[i]); + field_generator.GenerateFieldDescription(printer); + if (field_generator.needs_textformat_name_support()) { + text_format_decode_data.AddString(sorted_fields[i]->number(), + field_generator.generated_objc_name(), + field_generator.raw_field_name()); + } + } + printer->Outdent(); + printer->Outdent(); + printer->Outdent(); + + bool has_enums = enum_generators_.size(); + if (has_enums) { + printer->Print( + " };\n" + " static GPBMessageEnumDescription enums[] = {\n"); + printer->Indent(); + printer->Indent(); + printer->Indent(); + for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin(); + iter != enum_generators_.end(); ++iter) { + printer->Print("{ .enumDescriptorFunc = $name$_EnumDescriptor },\n", + "name", (*iter)->name()); + } + printer->Outdent(); + printer->Outdent(); + printer->Outdent(); + } + + bool has_extensions = sorted_extensions.size(); + if (has_extensions) { + printer->Print( + " };\n" + " static GPBExtensionRange ranges[] = {\n"); + printer->Indent(); + printer->Indent(); + printer->Indent(); + for (int i = 0; i < sorted_extensions.size(); i++) { + printer->Print("{ .start = $start$, .end = $end$ },\n", + "start", SimpleItoa(sorted_extensions[i]->start), + "end", SimpleItoa(sorted_extensions[i]->end)); + } + printer->Outdent(); + printer->Outdent(); + printer->Outdent(); + } + + map<string, string> vars; + vars["classname"] = class_name_; + vars["rootclassname"] = root_classname_; + vars["oneofs"] = has_oneofs ? "oneofs" : "NULL"; + vars["oneof_count"] = + has_oneofs ? "sizeof(oneofs) / sizeof(GPBMessageOneofDescription)" : "0"; + vars["enums"] = has_enums ? "enums" : "NULL"; + vars["enum_count"] = + has_enums ? "sizeof(enums) / sizeof(GPBMessageEnumDescription)" : "0"; + vars["ranges"] = has_extensions ? "ranges" : "NULL"; + vars["range_count"] = + has_extensions ? "sizeof(ranges) / sizeof(GPBExtensionRange)" : "0"; + vars["wireformat"] = + descriptor_->options().message_set_wire_format() ? "YES" : "NO"; + + printer->Print(" };\n"); + if (text_format_decode_data.num_entries() == 0) { + printer->Print( + vars, + " descriptor = [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n" + " rootClass:[$rootclassname$ class]\n" + " file:$rootclassname$_FileDescriptor()\n" + " fields:fields\n" + " fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)\n" + " oneofs:$oneofs$\n" + " oneofCount:$oneof_count$\n" + " enums:$enums$\n" + " enumCount:$enum_count$\n" + " ranges:$ranges$\n" + " rangeCount:$range_count$\n" + " storageSize:sizeof($classname$_Storage)\n" + " wireFormat:$wireformat$];\n"); + } else { + vars["extraTextFormatInfo"] = CEscape(text_format_decode_data.Data()); + printer->Print( + vars, + "#if GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n" + " const char *extraTextFormatInfo = NULL;\n" + "#else\n" + " static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n" + "#endif // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n" + " descriptor = [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n" + " rootClass:[$rootclassname$ class]\n" + " file:$rootclassname$_FileDescriptor()\n" + " fields:fields\n" + " fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)\n" + " oneofs:$oneofs$\n" + " oneofCount:$oneof_count$\n" + " enums:$enums$\n" + " enumCount:$enum_count$\n" + " ranges:$ranges$\n" + " rangeCount:$range_count$\n" + " storageSize:sizeof($classname$_Storage)\n" + " wireFormat:$wireformat$\n" + " extraTextFormatInfo:extraTextFormatInfo];\n"); + } + printer->Print( + " }\n" + " return descriptor;\n" + "}\n\n" + "@end\n\n"); + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateCFunctionImplementations(printer); + } + + for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin(); + iter != oneof_generators_.end(); ++iter) { + (*iter)->GenerateClearFunctionImplementation(printer); + } + } + + for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin(); + iter != enum_generators_.end(); ++iter) { + (*iter)->GenerateSource(printer); + } + + for (vector<MessageGenerator*>::iterator iter = + nested_message_generators_.begin(); + iter != nested_message_generators_.end(); ++iter) { + (*iter)->GenerateSource(printer); + } +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.h b/src/google/protobuf/compiler/objectivec/objectivec_message.h new file mode 100644 index 00000000..5992d0cf --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.h @@ -0,0 +1,103 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__ + +#include <string> +#include <set> +#include <vector> +#include <google/protobuf/compiler/objectivec/objectivec_field.h> +#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> +#include <google/protobuf/compiler/objectivec/objectivec_oneof.h> +#include <google/protobuf/stubs/common.h> + +namespace google { +namespace protobuf { + +namespace io { +class Printer; // printer.h +} // namespace io + +namespace compiler { +namespace objectivec { + +class ExtensionGenerator; +class EnumGenerator; + +class MessageGenerator { + public: + MessageGenerator(const string& root_classname, const Descriptor* descriptor); + ~MessageGenerator(); + + void GenerateStaticVariablesInitialization(io::Printer* printer, + bool* out_generated); + void GenerateEnumHeader(io::Printer* printer); + void GenerateMessageHeader(io::Printer* printer); + void GenerateSource(io::Printer* printer); + void GenerateExtensionRegistrationSource(io::Printer* printer); + void DetermineDependencies(set<string>* dependencies); + + // This only speaks for this message, not sub message/enums. + bool IsFiltered() const { return filter_reason_.length() > 0; } + // This message being filtered doesn't effect this, instead it covers if + // there are any nested messages or enums. + bool IsSubContentFiltered() const { return sub_content_filtered_; } + + private: + void GenerateParseFromMethodsHeader(io::Printer* printer); + + void GenerateSerializeOneFieldSource(io::Printer* printer, + const FieldDescriptor* field); + void GenerateSerializeOneExtensionRangeSource( + io::Printer* printer, const Descriptor::ExtensionRange* range); + + void GenerateMessageDescriptionSource(io::Printer* printer); + void GenerateDescriptionOneFieldSource(io::Printer* printer, + const FieldDescriptor* field); + + const string root_classname_; + const Descriptor* descriptor_; + FieldGeneratorMap field_generators_; + const string class_name_; + string filter_reason_; + bool sub_content_filtered_; + vector<ExtensionGenerator*> extension_generators_; + vector<EnumGenerator*> enum_generators_; + vector<MessageGenerator*> nested_message_generators_; + vector<OneofGenerator*> oneof_generators_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); +}; +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc new file mode 100644 index 00000000..9c4a4e44 --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc @@ -0,0 +1,90 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <map> +#include <string> + +#include <google/protobuf/compiler/objectivec/objectivec_message_field.h> +#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/wire_format.h> +#include <google/protobuf/stubs/strutil.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +namespace { + +void SetMessageVariables(const FieldDescriptor* descriptor, + map<string, string>* variables) { + const string& message_type = ClassName(descriptor->message_type()); + (*variables)["type"] = message_type; + (*variables)["containing_class"] = ClassName(descriptor->containing_type()); + (*variables)["storage_type"] = message_type; + (*variables)["group_or_message"] = + (descriptor->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message"; + + (*variables)["typeSpecific_value"] = "GPBStringifySymbol(" + message_type + ")"; +} + +} // namespace + +MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor) + : ObjCObjFieldGenerator(descriptor) { + SetMessageVariables(descriptor, &variables_); +} + +MessageFieldGenerator::~MessageFieldGenerator() {} + +bool MessageFieldGenerator::WantsHasProperty(void) const { + if (descriptor_->containing_oneof() != NULL) { + // If in a oneof, it uses the oneofcase instead of a has bit. + return false; + } + // In both proto2 & proto3, message fields have a has* property to tell + // when it is a non default value. + return true; +} + +RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( + const FieldDescriptor* descriptor) + : RepeatedFieldGenerator(descriptor) { + SetMessageVariables(descriptor, &variables_); + variables_["array_storage_type"] = "NSMutableArray"; +} + +RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h new file mode 100644 index 00000000..a1ac2d39 --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h @@ -0,0 +1,71 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__ + +#include <map> +#include <string> +#include <google/protobuf/compiler/objectivec/objectivec_field.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +class MessageFieldGenerator : public ObjCObjFieldGenerator { + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); + + protected: + MessageFieldGenerator(const FieldDescriptor* descriptor); + virtual ~MessageFieldGenerator(); + virtual bool WantsHasProperty(void) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); +}; + +class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator { + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); + + protected: + RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor); + virtual ~RepeatedMessageFieldGenerator(); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc new file mode 100644 index 00000000..77664c68 --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc @@ -0,0 +1,139 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <map> +#include <string> + +#include <google/protobuf/compiler/objectivec/objectivec_oneof.h> +#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/stubs/strutil.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +OneofGenerator::OneofGenerator(const OneofDescriptor* descriptor) + : descriptor_(descriptor) { + variables_["enum_name"] = OneofEnumName(descriptor_); + variables_["name"] = OneofName(descriptor_); + variables_["capitalized_name"] = OneofNameCapitalized(descriptor_); + variables_["raw_index"] = SimpleItoa(descriptor_->index()); + const Descriptor* msg_descriptor = descriptor_->containing_type(); + variables_["owning_message_class"] = ClassName(msg_descriptor); + + string comments; + SourceLocation location; + if (descriptor_->GetSourceLocation(&location)) { + comments = BuildCommentsString(location); + } else { + comments = ""; + } + variables_["comments"] = comments; +} + +OneofGenerator::~OneofGenerator() {} + +void OneofGenerator::SetOneofIndexBase(int index_base) { + int index = descriptor_->index() + index_base; + // Flip the sign to mark it as a oneof. + variables_["index"] = SimpleItoa(-index); +} + +void OneofGenerator::GenerateCaseEnum(io::Printer* printer) { + printer->Print( + variables_, + "typedef GPB_ENUM($enum_name$) {\n"); + printer->Indent(); + printer->Print( + variables_, + "$enum_name$_GPBUnsetOneOfCase = 0,\n"); + string enum_name = variables_["enum_name"]; + for (int j = 0; j < descriptor_->field_count(); j++) { + const FieldDescriptor* field = descriptor_->field(j); + string field_name = FieldNameCapitalized(field); + printer->Print( + "$enum_name$_$field_name$ = $field_number$,\n", + "enum_name", enum_name, + "field_name", field_name, + "field_number", SimpleItoa(field->number())); + } + printer->Outdent(); + printer->Print( + "};\n" + "\n"); +} + +void OneofGenerator::GeneratePublicCasePropertyDeclaration( + io::Printer* printer) { + printer->Print( + variables_, + "$comments$" + "@property(nonatomic, readonly) $enum_name$ $name$OneOfCase;\n" + "\n"); +} + +void OneofGenerator::GenerateClearFunctionDeclaration(io::Printer* printer) { + printer->Print( + variables_, + "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message);\n"); +} + +void OneofGenerator::GeneratePropertyImplementation(io::Printer* printer) { + printer->Print( + variables_, + "@dynamic $name$OneOfCase;\n"); +} + +void OneofGenerator::GenerateClearFunctionImplementation(io::Printer* printer) { + printer->Print( + variables_, + "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message) {\n" + " GPBDescriptor *descriptor = [message descriptor];\n" + " GPBOneofDescriptor *oneof = descriptor->oneofs_[$raw_index$];\n" + " GPBMaybeClearOneof(message, oneof, 0);\n" + "}\n"); +} + +void OneofGenerator::GenerateDescription(io::Printer* printer) { + printer->Print( + variables_, + "{\n" + " .name = \"$name$\",\n" + " .index = $index$,\n" + "},\n"); +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h new file mode 100644 index 00000000..77b7f800 --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h @@ -0,0 +1,77 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__ + +#include <string> +#include <set> +#include <vector> +#include <google/protobuf/descriptor.h> + +namespace google { +namespace protobuf { +namespace io { +class Printer; // printer.h +} +} + +namespace protobuf { +namespace compiler { +namespace objectivec { + +class OneofGenerator { + public: + OneofGenerator(const OneofDescriptor* descriptor); + ~OneofGenerator(); + + void SetOneofIndexBase(int index_base); + + void GenerateCaseEnum(io::Printer* printer); + + void GeneratePublicCasePropertyDeclaration(io::Printer* printer); + void GenerateClearFunctionDeclaration(io::Printer* printer); + + void GeneratePropertyImplementation(io::Printer* printer); + void GenerateClearFunctionImplementation(io::Printer* printer); + void GenerateDescription(io::Printer* printer); + + private: + const OneofDescriptor* descriptor_; + map<string, string> variables_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OneofGenerator); +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc new file mode 100644 index 00000000..8272c67b --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc @@ -0,0 +1,162 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <map> +#include <string> + +#include <google/protobuf/compiler/objectivec/objectivec_primitive_field.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/wire_format.h> +#include <google/protobuf/wire_format_lite_inl.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/substitute.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +using internal::WireFormat; +using internal::WireFormatLite; + +namespace { + +const char* PrimitiveTypeName(const FieldDescriptor* descriptor) { + ObjectiveCType type = GetObjectiveCType(descriptor); + switch (type) { + case OBJECTIVECTYPE_INT32: + return "int32_t"; + case OBJECTIVECTYPE_UINT32: + return "uint32_t"; + case OBJECTIVECTYPE_INT64: + return "int64_t"; + case OBJECTIVECTYPE_UINT64: + return "uint64_t"; + case OBJECTIVECTYPE_FLOAT: + return "float"; + case OBJECTIVECTYPE_DOUBLE: + return "double"; + case OBJECTIVECTYPE_BOOLEAN: + return "BOOL"; + case OBJECTIVECTYPE_STRING: + return "NSString"; + case OBJECTIVECTYPE_DATA: + return "NSData"; + case OBJECTIVECTYPE_ENUM: + return "int32_t"; + case OBJECTIVECTYPE_MESSAGE: + return NULL; + } +} + +const char* PrimitiveArrayTypeName(const FieldDescriptor* descriptor) { + ObjectiveCType type = GetObjectiveCType(descriptor); + switch (type) { + case OBJECTIVECTYPE_INT32: + return "Int32"; + case OBJECTIVECTYPE_UINT32: + return "UInt32"; + case OBJECTIVECTYPE_INT64: + return "Int64"; + case OBJECTIVECTYPE_UINT64: + return "UInt64"; + case OBJECTIVECTYPE_FLOAT: + return "Float"; + case OBJECTIVECTYPE_DOUBLE: + return "Double"; + case OBJECTIVECTYPE_BOOLEAN: + return "Bool"; + case OBJECTIVECTYPE_STRING: + return ""; // Want NSArray + case OBJECTIVECTYPE_DATA: + return ""; // Want NSArray + case OBJECTIVECTYPE_ENUM: + return "Enum"; + case OBJECTIVECTYPE_MESSAGE: + return ""; // Want NSArray + } +} + +void SetPrimitiveVariables(const FieldDescriptor* descriptor, + map<string, string>* variables) { + std::string primitive_name = PrimitiveTypeName(descriptor); + (*variables)["type"] = primitive_name; + (*variables)["storage_type"] = primitive_name; +} + +} // namespace + +PrimitiveFieldGenerator::PrimitiveFieldGenerator( + const FieldDescriptor* descriptor) + : SingleFieldGenerator(descriptor) { + SetPrimitiveVariables(descriptor, &variables_); +} + +PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} + +PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator( + const FieldDescriptor* descriptor) + : ObjCObjFieldGenerator(descriptor) { + SetPrimitiveVariables(descriptor, &variables_); + variables_["property_storage_attribute"] = "copy"; +} + +PrimitiveObjFieldGenerator::~PrimitiveObjFieldGenerator() {} + +RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( + const FieldDescriptor* descriptor) + : RepeatedFieldGenerator(descriptor) { + SetPrimitiveVariables(descriptor, &variables_); + + string base_name = PrimitiveArrayTypeName(descriptor); + if (base_name.length()) { + variables_["array_storage_type"] = "GPB" + base_name + "Array"; + } else { + variables_["array_storage_type"] = "NSMutableArray"; + } +} + +RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} + +void RepeatedPrimitiveFieldGenerator::FinishInitialization(void) { + RepeatedFieldGenerator::FinishInitialization(); + if (IsPrimitiveType(descriptor_)) { + // No comment needed for primitive types. + variables_["array_comment"] = ""; + } +} + + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h new file mode 100644 index 00000000..b3599297 --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h @@ -0,0 +1,82 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__ + +#include <map> +#include <string> +#include <google/protobuf/compiler/objectivec/objectivec_field.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +class PrimitiveFieldGenerator : public SingleFieldGenerator { + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); + + protected: + PrimitiveFieldGenerator(const FieldDescriptor* descriptor); + virtual ~PrimitiveFieldGenerator(); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); +}; + +class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator { + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); + + protected: + PrimitiveObjFieldGenerator(const FieldDescriptor* descriptor); + virtual ~PrimitiveObjFieldGenerator(); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveObjFieldGenerator); +}; + +class RepeatedPrimitiveFieldGenerator : public RepeatedFieldGenerator { + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); + + protected: + RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor); + virtual ~RepeatedPrimitiveFieldGenerator(); + virtual void FinishInitialization(void); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator); +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__ diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc index 4b3efe48..c50cdf54 100644 --- a/src/google/protobuf/compiler/parser.cc +++ b/src/google/protobuf/compiler/parser.cc @@ -277,27 +277,39 @@ bool Parser::ConsumeString(string* output, const char* error) { } } -bool Parser::TryConsumeEndOfDeclaration(const char* text, - const LocationRecorder* location) { +bool Parser::TryConsumeEndOfDeclaration( + const char* text, const LocationRecorder* location) { if (LookingAt(text)) { string leading, trailing; - input_->NextWithComments(&trailing, NULL, &leading); + vector<string> detached; + input_->NextWithComments(&trailing, &detached, &leading); // Save the leading comments for next time, and recall the leading comments // from last time. leading.swap(upcoming_doc_comments_); if (location != NULL) { - location->AttachComments(&leading, &trailing); + upcoming_detached_comments_.swap(detached); + location->AttachComments(&leading, &trailing, &detached); + } else if (strcmp(text, "}") == 0) { + // If the current location is null and we are finishing the current scope, + // drop pending upcoming detached comments. + upcoming_detached_comments_.swap(detached); + } else { + // Otherwise, append the new detached comments to the existing upcoming + // detached comments. + upcoming_detached_comments_.insert(upcoming_detached_comments_.end(), + detached.begin(), detached.end()); } + return true; } else { return false; } } -bool Parser::ConsumeEndOfDeclaration(const char* text, - const LocationRecorder* location) { +bool Parser::ConsumeEndOfDeclaration( + const char* text, const LocationRecorder* location) { if (TryConsumeEndOfDeclaration(text, location)) { return true; } else { @@ -390,7 +402,8 @@ void Parser::LocationRecorder::RecordLegacyLocation(const Message* descriptor, } void Parser::LocationRecorder::AttachComments( - string* leading, string* trailing) const { + string* leading, string* trailing, + vector<string>* detached_comments) const { GOOGLE_CHECK(!location_->has_leading_comments()); GOOGLE_CHECK(!location_->has_trailing_comments()); @@ -400,6 +413,11 @@ void Parser::LocationRecorder::AttachComments( if (!trailing->empty()) { location_->mutable_trailing_comments()->swap(*trailing); } + for (int i = 0; i < detached_comments->size(); ++i) { + location_->add_leading_detached_comments()->swap( + (*detached_comments)[i]); + } + detached_comments->clear(); } // ------------------------------------------------------------------- @@ -451,16 +469,18 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { SourceCodeInfo source_code_info; source_code_info_ = &source_code_info; + vector<string> top_doc_comments; if (LookingAtType(io::Tokenizer::TYPE_START)) { // Advance to first token. - input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_); + input_->NextWithComments(NULL, &upcoming_detached_comments_, + &upcoming_doc_comments_); } { LocationRecorder root_location(this); if (require_syntax_identifier_ || LookingAt("syntax")) { - if (!ParseSyntaxIdentifier()) { + if (!ParseSyntaxIdentifier(root_location)) { // Don't attempt to parse the file if we didn't recognize the syntax // identifier. return false; @@ -468,6 +488,10 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { // Store the syntax into the file. if (file != NULL) file->set_syntax(syntax_identifier_); } else if (!stop_after_syntax_identifier_) { + GOOGLE_LOG(WARNING) << "No syntax specified for the proto file. " + << "Please use 'syntax = \"proto2\";' or " + << "'syntax = \"proto3\";' to specify a syntax " + << "version. (Defaulted to proto2 syntax.)"; syntax_identifier_ = "proto2"; } @@ -482,7 +506,8 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { if (LookingAt("}")) { AddError("Unmatched \"}\"."); - input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_); + input_->NextWithComments(NULL, &upcoming_detached_comments_, + &upcoming_doc_comments_); } } } @@ -494,7 +519,9 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { return !had_errors_; } -bool Parser::ParseSyntaxIdentifier() { +bool Parser::ParseSyntaxIdentifier(const LocationRecorder& parent) { + LocationRecorder syntax_location(parent, + FileDescriptorProto::kSyntaxFieldNumber); DO(Consume( "syntax", "File must begin with a syntax statement, e.g. 'syntax = \"proto2\";'.")); @@ -502,7 +529,7 @@ bool Parser::ParseSyntaxIdentifier() { io::Tokenizer::Token syntax_token = input_->current(); string syntax; DO(ConsumeString(&syntax, "Expected syntax identifier.")); - DO(ConsumeEndOfDeclaration(";", NULL)); + DO(ConsumeEndOfDeclaration(";", &syntax_location)); syntax_identifier_ = syntax; @@ -1267,7 +1294,6 @@ bool Parser::ParseOption(Message* options, DO(ConsumeEndOfDeclaration(";", &location)); } - return true; } @@ -1632,8 +1658,14 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method, // Parse input type. DO(Consume("(")); { - if (TryConsume("stream")) { + if (LookingAt("stream")) { + LocationRecorder location( + method_location, MethodDescriptorProto::kClientStreamingFieldNumber); + location.RecordLegacyLocation( + method, DescriptorPool::ErrorCollector::OTHER); method->set_client_streaming(true); + DO(Consume("stream")); + } LocationRecorder location(method_location, MethodDescriptorProto::kInputTypeFieldNumber); @@ -1647,8 +1679,14 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method, DO(Consume("returns")); DO(Consume("(")); { - if (TryConsume("stream")) { + if (LookingAt("stream")) { + LocationRecorder location( + method_location, MethodDescriptorProto::kServerStreamingFieldNumber); + location.RecordLegacyLocation( + method, DescriptorPool::ErrorCollector::OTHER); + DO(Consume("stream")); method->set_server_streaming(true); + } LocationRecorder location(method_location, MethodDescriptorProto::kOutputTypeFieldNumber); @@ -1660,10 +1698,9 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method, if (LookingAt("{")) { // Options! - DO(ParseOptions(method_location, - containing_file, - MethodDescriptorProto::kOptionsFieldNumber, - method->mutable_options())); + DO(ParseMethodOptions(method_location, containing_file, + MethodDescriptorProto::kOptionsFieldNumber, + method->mutable_options())); } else { DO(ConsumeEndOfDeclaration(";", &method_location)); } @@ -1672,10 +1709,10 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method, } -bool Parser::ParseOptions(const LocationRecorder& parent_location, - const FileDescriptorProto* containing_file, - const int optionsFieldNumber, - Message* mutable_options) { +bool Parser::ParseMethodOptions(const LocationRecorder& parent_location, + const FileDescriptorProto* containing_file, + const int optionsFieldNumber, + Message* mutable_options) { // Options! ConsumeEndOfDeclaration("{", &parent_location); while (!TryConsumeEndOfDeclaration("}", NULL)) { @@ -1689,8 +1726,8 @@ bool Parser::ParseOptions(const LocationRecorder& parent_location, } else { LocationRecorder location(parent_location, optionsFieldNumber); - if (!ParseOption(mutable_options, location, containing_file, - OPTION_STATEMENT)) { + if (!ParseOption(mutable_options, location, + containing_file, OPTION_STATEMENT)) { // This statement failed to parse. Skip it, but keep looping to // parse other statements. SkipStatement(); @@ -1843,7 +1880,7 @@ bool SourceLocationTable::Find( DescriptorPool::ErrorCollector::ErrorLocation location, int* line, int* column) const { const pair<int, int>* result = - FindOrNull(location_map_, make_pair(descriptor, location)); + FindOrNull(location_map_, std::make_pair(descriptor, location)); if (result == NULL) { *line = -1; *column = 0; @@ -1859,7 +1896,8 @@ void SourceLocationTable::Add( const Message* descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, int line, int column) { - location_map_[make_pair(descriptor, location)] = make_pair(line, column); + location_map_[std::make_pair(descriptor, location)] = + std::make_pair(line, column); } void SourceLocationTable::Clear() { diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h index a15cc705..7cb1678a 100644 --- a/src/google/protobuf/compiler/parser.h +++ b/src/google/protobuf/compiler/parser.h @@ -185,10 +185,13 @@ class LIBPROTOBUF_EXPORT Parser { // have been passed around by const reference, for no particularly good // reason. We should probably go through and change them all to mutable // pointer to make this more intuitive. - bool TryConsumeEndOfDeclaration(const char* text, - const LocationRecorder* location); - bool ConsumeEndOfDeclaration(const char* text, - const LocationRecorder* location); + bool TryConsumeEndOfDeclaration( + const char* text, const LocationRecorder* location); + bool TryConsumeEndOfDeclarationFinishScope( + const char* text, const LocationRecorder* location); + + bool ConsumeEndOfDeclaration( + const char* text, const LocationRecorder* location); // ----------------------------------------------------------------- // Error logging helpers @@ -253,9 +256,13 @@ class LIBPROTOBUF_EXPORT Parser { // // TODO(kenton): See comment on TryConsumeEndOfDeclaration(), above, for // why this is const. - void AttachComments(string* leading, string* trailing) const; + void AttachComments(string* leading, string* trailing, + vector<string>* detached_comments) const; private: + // Indexes of parent and current location in the parent + // SourceCodeInfo.location repeated field. For top-level elements, + // parent_index_ is -1. Parser* parser_; SourceCodeInfo::Location* location_; @@ -268,7 +275,7 @@ class LIBPROTOBUF_EXPORT Parser { // Parses the "syntax = \"proto2\";" line at the top of the file. Returns // false if it failed to parse or if the syntax identifier was not // recognized. - bool ParseSyntaxIdentifier(); + bool ParseSyntaxIdentifier(const LocationRecorder& parent); // These methods parse various individual bits of code. They return // false if they completely fail to parse the construct. In this case, @@ -302,9 +309,6 @@ class LIBPROTOBUF_EXPORT Parser { RepeatedField<int32>* weak_dependency, const LocationRecorder& root_location, const FileDescriptorProto* containing_file); - bool ParseOption(Message* options, - const LocationRecorder& options_location, - const FileDescriptorProto* containing_file); // These methods parse the contents of a message, enum, or service type and // add them to the given object. They consume the entire block including @@ -397,10 +401,10 @@ class LIBPROTOBUF_EXPORT Parser { // Parse options of a single method or stream. - bool ParseOptions(const LocationRecorder& parent_location, - const FileDescriptorProto* containing_file, - const int optionsFieldNumber, - Message* mutable_options); + bool ParseMethodOptions(const LocationRecorder& parent_location, + const FileDescriptorProto* containing_file, + const int optionsFieldNumber, + Message* mutable_options); // Parse "required", "optional", or "repeated" and fill in "label" // with the value. Returns true if shuch a label is consumed. @@ -497,6 +501,13 @@ class LIBPROTOBUF_EXPORT Parser { // yet; use ConsumeEndOfDeclaration() to get the complete comments. string upcoming_doc_comments_; + // Detached comments are not connected to any syntax entities. Elements in + // this vector are paragraphs of comments separated by empty lines. The + // detached comments will be put into the leading_detached_comments field for + // the next element (See SourceCodeInfo.Location in descriptor.proto), when + // ConsumeEndOfDeclaration() is called. + vector<string> upcoming_detached_comments_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser); }; diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc index 00112999..1684bebe 100644 --- a/src/google/protobuf/compiler/parser_unittest.cc +++ b/src/google/protobuf/compiler/parser_unittest.cc @@ -216,6 +216,15 @@ TEST_F(ParserTest, StopAfterSyntaxIdentifierWithErrors) { EXPECT_EQ("1:9: Expected syntax identifier.\n", error_collector_.text_); } +TEST_F(ParserTest, WarnIfSyntaxIdentifierOmmitted) { + SetupParser("message A {}"); + FileDescriptorProto file; + CaptureTestStderr(); + EXPECT_TRUE(parser_->Parse(input_.get(), &file)); + EXPECT_TRUE( + GetCapturedTestStderr().find("No syntax specified") != string::npos); +} + // =================================================================== typedef ParserTest ParseMessageTest; @@ -370,35 +379,49 @@ TEST_F(ParseMessageTest, FieldDefaults) { #define ETC "name:\"foo\" label:LABEL_REQUIRED number:1" "message_type {" " name: \"TestMessage\"" - " field { type:TYPE_INT32 default_value:\"1\" "ETC" }" - " field { type:TYPE_INT32 default_value:\"-2\" "ETC" }" - " field { type:TYPE_INT64 default_value:\"3\" "ETC" }" - " field { type:TYPE_INT64 default_value:\"-4\" "ETC" }" - " field { type:TYPE_UINT32 default_value:\"5\" "ETC" }" - " field { type:TYPE_UINT64 default_value:\"6\" "ETC" }" - " field { type:TYPE_FLOAT default_value:\"7.5\" "ETC" }" - " field { type:TYPE_FLOAT default_value:\"-8.5\" "ETC" }" - " field { type:TYPE_FLOAT default_value:\"9\" "ETC" }" - " field { type:TYPE_DOUBLE default_value:\"10.5\" "ETC" }" - " field { type:TYPE_DOUBLE default_value:\"-11.5\" "ETC" }" - " field { type:TYPE_DOUBLE default_value:\"12\" "ETC" }" - " field { type:TYPE_DOUBLE default_value:\"inf\" "ETC" }" - " field { type:TYPE_DOUBLE default_value:\"-inf\" "ETC" }" - " field { type:TYPE_DOUBLE default_value:\"nan\" "ETC" }" - " field { type:TYPE_STRING default_value:\"13\\001\" "ETC" }" - " field { type:TYPE_STRING default_value:\"abc\" "ETC" }" - " field { type:TYPE_BYTES default_value:\"14\\\\002\" "ETC" }" - " field { type:TYPE_BYTES default_value:\"abc\" "ETC" }" - " field { type:TYPE_BOOL default_value:\"true\" "ETC" }" - " field { type_name:\"Foo\" default_value:\"FOO\" "ETC" }" - - " field { type:TYPE_INT32 default_value:\"2147483647\" "ETC" }" - " field { type:TYPE_INT32 default_value:\"-2147483648\" "ETC" }" - " field { type:TYPE_UINT32 default_value:\"4294967295\" "ETC" }" - " field { type:TYPE_INT64 default_value:\"9223372036854775807\" "ETC" }" - " field { type:TYPE_INT64 default_value:\"-9223372036854775808\" "ETC" }" - " field { type:TYPE_UINT64 default_value:\"18446744073709551615\" "ETC" }" - " field { type:TYPE_DOUBLE default_value:\"43981\" "ETC" }" + " field { type:TYPE_INT32 default_value:\"1\" " ETC " }" + " field { type:TYPE_INT32 default_value:\"-2\" " ETC " }" + " field { type:TYPE_INT64 default_value:\"3\" " ETC " }" + " field { type:TYPE_INT64 default_value:\"-4\" " ETC " }" + " field { type:TYPE_UINT32 default_value:\"5\" " ETC " }" + " field { type:TYPE_UINT64 default_value:\"6\" " ETC " }" + " field { type:TYPE_FLOAT default_value:\"7.5\" " ETC " }" + " field { type:TYPE_FLOAT default_value:\"-8.5\" " ETC " }" + " field { type:TYPE_FLOAT default_value:\"9\" " ETC " }" + " field { type:TYPE_DOUBLE default_value:\"10.5\" " ETC " }" + " field { type:TYPE_DOUBLE default_value:\"-11.5\" " ETC " }" + " field { type:TYPE_DOUBLE default_value:\"12\" " ETC " }" + " field { type:TYPE_DOUBLE default_value:\"inf\" " ETC " }" + " field { type:TYPE_DOUBLE default_value:\"-inf\" " ETC " }" + " field { type:TYPE_DOUBLE default_value:\"nan\" " ETC " }" + " field { type:TYPE_STRING default_value:\"13\\001\" " ETC " }" + " field { type:TYPE_STRING default_value:\"abc\" " ETC " }" + " field { type:TYPE_BYTES default_value:\"14\\\\002\" " ETC " }" + " field { type:TYPE_BYTES default_value:\"abc\" " ETC " }" + " field { type:TYPE_BOOL default_value:\"true\" " ETC " }" + " field { type_name:\"Foo\" default_value:\"FOO\" " ETC " }" + + " field {" + " type:TYPE_INT32 default_value:\"2147483647\" " ETC + " }" + " field {" + " type:TYPE_INT32 default_value:\"-2147483648\" " ETC + " }" + " field {" + " type:TYPE_UINT32 default_value:\"4294967295\" " ETC + " }" + " field {" + " type:TYPE_INT64 default_value:\"9223372036854775807\" " ETC + " }" + " field {" + " type:TYPE_INT64 default_value:\"-9223372036854775808\" " ETC + " }" + " field {" + " type:TYPE_UINT64 default_value:\"18446744073709551615\" " ETC + " }" + " field {" + " type:TYPE_DOUBLE default_value:\"43981\" " ETC + " }" "}"); #undef ETC } @@ -1548,7 +1571,7 @@ void SortMessages(DescriptorProto *descriptor_proto) { } DescriptorProto **data = descriptor_proto->mutable_nested_type()->mutable_data(); - sort(data, data + size, CompareDescriptorNames()); + std::sort(data, data + size, CompareDescriptorNames()); } // Sorts DescriptorProtos belonging to a FileDescriptorProto, by name. @@ -1560,7 +1583,7 @@ void SortMessages(FileDescriptorProto *file_descriptor_proto) { } DescriptorProto **data = file_descriptor_proto->mutable_message_type()->mutable_data(); - sort(data, data + size, CompareDescriptorNames()); + std::sort(data, data + size, CompareDescriptorNames()); } // Strips the message and enum field type names for comparison purpose only. @@ -1680,25 +1703,52 @@ TEST_F(ParseDescriptorDebugTest, TestCustomOptions) { // places. TEST_F(ParseDescriptorDebugTest, TestCommentsInDebugString) { SetupParser( + "// Detached comment before syntax.\n" + "\n" + "// Syntax comment.\n" + "syntax = \"proto2\";\n" + "\n" + "// Detached comment before package.\n" + "\n" + "// Package comment.\n" + "package comment_test;\n" + "\n" + "// Detached comment before TestMessage1.\n" + "\n" "// Message comment.\n" "message TestMessage1 {\n" + "\n" + " // Detached comment before foo.\n" + "\n" " // Field comment.\n" " optional int32 foo = 1;\n" "\n" + " // Detached comment before NestedMessage.\n" + "\n" " // Nested-message comment.\n" " message NestedMessage {\n" " optional int32 bar = 1;\n" " }\n" "}\n" "\n" + "// Detached comment before MyEnumType.\n" + "\n" "// Enum comment.\n" "enum MyEnumType {\n" + "\n" + " // Detached comment before ASDF.\n" + "\n" " // Enum-value comment.\n" " ASDF = 1;\n" "}\n" "\n" + "// Detached comment before MyService.\n" + "\n" "// Service comment.\n" "service MyService {\n" + "\n" + " // Detached comment before MyRPCCall.\n" + "\n" " // RPC comment.\n" " rpc MyRPCCall(TestMessage1) returns (TestMessage1) { }\n" "}\n"); @@ -1722,22 +1772,34 @@ TEST_F(ParseDescriptorDebugTest, TestCommentsInDebugString) { const string debug_string = descriptor->DebugStringWithOptions(debug_string_options); - // Ensure that each of the comments appears somewhere in the DebugString(), - // and that these comments appear in order. We don't test the exact comment - // placement or formatting, because we do not want to be too fragile here. + // Ensure that each of the comments appears somewhere in the DebugString(). + // We don't test the exact comment placement or formatting, because we do not + // want to be too fragile here. const char* expected_comments[] = { + "Detached comment before syntax.", + "Syntax comment.", + "Detached comment before package.", + "Package comment.", + "Detached comment before TestMessage1.", "Message comment.", + "Detached comment before foo.", "Field comment", + "Detached comment before NestedMessage.", "Nested-message comment", + "Detached comment before MyEnumType.", "Enum comment", + "Detached comment before ASDF.", "Enum-value comment", + "Detached comment before MyService.", "Service comment", + "Detached comment before MyRPCCall.", "RPC comment", }; for (int i = 0; i < GOOGLE_ARRAYSIZE(expected_comments); ++i) { string::size_type found_pos = debug_string.find(expected_comments[i]); - ASSERT_TRUE(found_pos != string::npos); + EXPECT_TRUE(found_pos != string::npos) + << "\"" << expected_comments[i] << "\" not found."; } } @@ -1907,8 +1969,8 @@ class SourceInfoTest : public ParserTest { return false; } - spans_.insert(make_pair(SpanKey(*descriptor_proto, field, index), - &location)); + spans_.insert( + std::make_pair(SpanKey(*descriptor_proto, field, index), &location)); } return true; @@ -1929,16 +1991,18 @@ class SourceInfoTest : public ParserTest { bool HasSpan(char start_marker, char end_marker, const Message& descriptor_proto) { return HasSpanWithComment( - start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL); + start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL, NULL); } bool HasSpanWithComment(char start_marker, char end_marker, const Message& descriptor_proto, const char* expected_leading_comments, - const char* expected_trailing_comments) { + const char* expected_trailing_comments, + const char* expected_leading_detached_comments) { return HasSpanWithComment( start_marker, end_marker, descriptor_proto, NULL, -1, - expected_leading_comments, expected_trailing_comments); + expected_leading_comments, expected_trailing_comments, + expected_leading_detached_comments); } bool HasSpan(char start_marker, char end_marker, @@ -1950,14 +2014,15 @@ class SourceInfoTest : public ParserTest { const Message& descriptor_proto, const string& field_name, int index) { return HasSpan(start_marker, end_marker, descriptor_proto, - field_name, index, NULL, NULL); + field_name, index, NULL, NULL, NULL); } bool HasSpan(char start_marker, char end_marker, const Message& descriptor_proto, const string& field_name, int index, const char* expected_leading_comments, - const char* expected_trailing_comments) { + const char* expected_trailing_comments, + const char* expected_leading_detached_comments) { const FieldDescriptor* field = descriptor_proto.GetDescriptor()->FindFieldByName(field_name); if (field == NULL) { @@ -1968,12 +2033,13 @@ class SourceInfoTest : public ParserTest { return HasSpanWithComment( start_marker, end_marker, descriptor_proto, field, index, - expected_leading_comments, expected_trailing_comments); + expected_leading_comments, expected_trailing_comments, + expected_leading_detached_comments); } bool HasSpan(const Message& descriptor_proto) { return HasSpanWithComment( - '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL); + '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL, NULL); } bool HasSpan(const Message& descriptor_proto, const string& field_name) { @@ -1985,11 +2051,12 @@ class SourceInfoTest : public ParserTest { return HasSpan('\0', '\0', descriptor_proto, field_name, index); } - bool HasSpanWithComment(char start_marker, char end_marker, - const Message& descriptor_proto, - const FieldDescriptor* field, int index, - const char* expected_leading_comments, - const char* expected_trailing_comments) { + bool HasSpanWithComment( + char start_marker, char end_marker, const Message& descriptor_proto, + const FieldDescriptor* field, int index, + const char* expected_leading_comments, + const char* expected_trailing_comments, + const char* expected_leading_detached_comments) { pair<SpanMap::iterator, SpanMap::iterator> range = spans_.equal_range(SpanKey(descriptor_proto, field, index)); @@ -2028,6 +2095,13 @@ class SourceInfoTest : public ParserTest { EXPECT_EQ(expected_trailing_comments, iter->second->trailing_comments()); } + if (expected_leading_detached_comments == NULL) { + EXPECT_EQ(0, iter->second->leading_detached_comments_size()); + } else { + EXPECT_EQ( + expected_leading_detached_comments, + Join(iter->second->leading_detached_comments(), "\n")); + } spans_.erase(iter); return true; @@ -2078,7 +2152,7 @@ class SourceInfoTest : public ParserTest { text_without_markers_ += '$'; ++column; } else { - markers_[*text] = make_pair(line, column); + markers_[*text] = std::make_pair(line, column); ++text; GOOGLE_CHECK_EQ('$', *text); } @@ -2097,7 +2171,7 @@ class SourceInfoTest : public ParserTest { TEST_F(SourceInfoTest, BasicFileDecls) { EXPECT_TRUE(Parse( - "$a$syntax = \"proto2\";\n" + "$a$syntax = \"proto2\";$i$\n" "package $b$foo.bar$c$;\n" "import $d$\"baz.proto\"$e$;\n" "import $f$\"qux.proto\"$g$;$h$\n" @@ -2108,6 +2182,7 @@ TEST_F(SourceInfoTest, BasicFileDecls) { EXPECT_TRUE(HasSpan('b', 'c', file_, "package")); EXPECT_TRUE(HasSpan('d', 'e', file_, "dependency", 0)); EXPECT_TRUE(HasSpan('f', 'g', file_, "dependency", 1)); + EXPECT_TRUE(HasSpan('a', 'i', file_, "syntax")); } TEST_F(SourceInfoTest, Messages) { @@ -2538,6 +2613,9 @@ TEST_F(SourceInfoTest, ScopedOptions) { " rpc M(X) returns(Y) {\n" " $g$option mopt = 1;$h$\n" " }\n" + " rpc MS4($1$stream$2$ X) returns($3$stream$4$ Y) {\n" + " $k$option mopt = 1;$l$\n" + " }\n" "}\n")); EXPECT_TRUE(HasSpan('a', 'b', file_.message_type(0).options())); @@ -2597,6 +2675,26 @@ TEST_F(SourceInfoTest, ScopedOptions) { .uninterpreted_option(0).name(0), "name_part")); EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() .uninterpreted_option(0), "positive_int_value")); + + EXPECT_TRUE(HasSpan('k', 'l', file_.service(0).method(1).options())); + EXPECT_TRUE(HasSpan(file_.service(0).method(1))); + EXPECT_TRUE(HasSpan(file_.service(0).method(1), "name")); + EXPECT_TRUE(HasSpan(file_.service(0).method(1), "input_type")); + EXPECT_TRUE(HasSpan(file_.service(0).method(1), "output_type")); + EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() + .uninterpreted_option(0))); + EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() + .uninterpreted_option(0), "name")); + EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() + .uninterpreted_option(0).name(0))); + EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() + .uninterpreted_option(0).name(0), "name_part")); + EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() + .uninterpreted_option(0), "positive_int_value")); + EXPECT_TRUE(HasSpan('1', '2', file_.service(0).method(1), + "client_streaming")); + EXPECT_TRUE(HasSpan('3', '4', file_.service(0).method(1), + "server_streaming")); } TEST_F(SourceInfoTest, FieldOptions) { @@ -2682,7 +2780,7 @@ TEST_F(SourceInfoTest, DocComments) { " // Foo trailing\n" " // line 2\n" "\n" - " // ignored\n" + " // detached\n" "\n" " // bar leading\n" " $b$optional int32 bar = 1;$c$\n" @@ -2696,10 +2794,12 @@ TEST_F(SourceInfoTest, DocComments) { EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, " Foo leading\n line 2\n", - " Foo trailing\n line 2\n")); + " Foo trailing\n line 2\n", + NULL)); EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, " bar leading\n", - " bar trailing\n")); + " bar trailing\n", + " detached\n")); // Ignore these. EXPECT_TRUE(HasSpan(file_)); @@ -2712,21 +2812,23 @@ TEST_F(SourceInfoTest, DocComments) { TEST_F(SourceInfoTest, DocComments2) { EXPECT_TRUE(Parse( - "// ignored\n" - "syntax = \"proto2\";\n" + "// detached before message.\n" + "\n" "// Foo leading\n" "// line 2\n" "$a$message Foo {\n" " /* Foo trailing\n" " * line 2 */\n" - " // ignored\n" + " // detached\n" " /* bar leading\n" " */" " $b$optional int32 bar = 1;$c$ // bar trailing\n" - " // ignored\n" + " // ignored detached\n" "}$d$\n" "// ignored\n" "\n" + "// detached before option\n" + "\n" "// option leading\n" "$e$option baz = 123;$f$\n" "// option trailing\n" @@ -2738,13 +2840,16 @@ TEST_F(SourceInfoTest, DocComments2) { EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, " Foo leading\n line 2\n", - " Foo trailing\n line 2 ")); + " Foo trailing\n line 2 ", + " detached before message.\n")); EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, " bar leading\n", - " bar trailing\n")); + " bar trailing\n", + " detached\n")); EXPECT_TRUE(HasSpanWithComment('e', 'f', baz, " option leading\n", - " option trailing\n")); + " option trailing\n", + " detached before option\n")); // Ignore these. EXPECT_TRUE(HasSpan(file_)); @@ -2775,7 +2880,8 @@ TEST_F(SourceInfoTest, DocComments3) { EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, " bar leading\n", - " bar trailing\n")); + " bar trailing\n", + NULL)); // Ignore these. EXPECT_TRUE(HasSpan(file_)); @@ -2795,25 +2901,63 @@ TEST_F(SourceInfoTest, DocComments3) { bar.options().uninterpreted_option(0), "aggregate_value")); } +TEST_F(SourceInfoTest, DocCommentsTopLevel) { + EXPECT_TRUE(Parse( + "// detached before syntax paragraph 1\n" + "\n" + "// detached before syntax paragraph 2\n" + "\n" + "// syntax leading\n" + "$a$syntax = \"proto2\";$b$\n" + "// syntax trailing\n" + "\n" + "// syntax-package detached comments\n" + "\n" + ";\n" + "\n" + "// detached after empty before package\n" + "\n" + "// package leading\n" + "package $c$foo$d$;\n" + "// package trailing\n" + "\n" + "// ignored detach\n" + "\n")); + + EXPECT_TRUE(HasSpan('a', 'b', file_, "syntax", -1, + " syntax leading\n", + " syntax trailing\n", + " detached before syntax paragraph 1\n" + "\n" + " detached before syntax paragraph 2\n")); + EXPECT_TRUE(HasSpan('c', 'd', file_, "package", -1, + " package leading\n", + " package trailing\n", + " syntax-package detached comments\n" + "\n" + " detached after empty before package\n")); + + // ignore these. + EXPECT_TRUE(HasSpan(file_)); +} + TEST_F(SourceInfoTest, DocCommentsOneof) { EXPECT_TRUE(Parse( - "// ignored\n" - "syntax = \"proto2\";\n" "// Foo leading\n" "$a$message Foo {\n" " /* Foo trailing\n" " */\n" - " // ignored\n" + " // detached before oneof\n" " /* bar leading\n" " * line 2 */\n" " $b$oneof bar {\n" " /* bar trailing\n" " * line 2 */\n" - " // ignored\n" + " // detached before bar_int\n" " /* bar_int leading\n" " */\n" " $c$int32 bar_int = 1;$d$ // bar_int trailing\n" - " // ignored\n" + " // detach comment ignored\n" " }$e$\n" "}$f$\n")); @@ -2823,13 +2967,16 @@ TEST_F(SourceInfoTest, DocCommentsOneof) { EXPECT_TRUE(HasSpanWithComment('a', 'f', foo, " Foo leading\n", - " Foo trailing\n")); + " Foo trailing\n", + NULL)); EXPECT_TRUE(HasSpanWithComment('b', 'e', bar, " bar leading\n line 2 ", - " bar trailing\n line 2 ")); + " bar trailing\n line 2 ", + " detached before oneof\n")); EXPECT_TRUE(HasSpanWithComment('c', 'd', bar_int, " bar_int leading\n", - " bar_int trailing\n")); + " bar_int trailing\n", + " detached before bar_int\n")); // Ignore these. EXPECT_TRUE(HasSpan(file_)); diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc index 9011a6bd..ad501acf 100644 --- a/src/google/protobuf/compiler/plugin.cc +++ b/src/google/protobuf/compiler/plugin.cc @@ -95,7 +95,7 @@ class GeneratorResponseContext : public GeneratorContext { int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { if (argc > 1) { - cerr << argv[0] << ": Unknown option: " << argv[1] << endl; + std::cerr << argv[0] << ": Unknown option: " << argv[1] << std::endl; return 1; } @@ -106,7 +106,8 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { CodeGeneratorRequest request; if (!request.ParseFromFileDescriptor(STDIN_FILENO)) { - cerr << argv[0] << ": protoc sent unparseable request to plugin." << endl; + std::cerr << argv[0] << ": protoc sent unparseable request to plugin." + << std::endl; return 1; } @@ -123,9 +124,9 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { for (int i = 0; i < request.file_to_generate_size(); i++) { parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i))); if (parsed_files.back() == NULL) { - cerr << argv[0] << ": protoc asked plugin to generate a file but " - "did not provide a descriptor for the file: " - << request.file_to_generate(i) << endl; + std::cerr << argv[0] << ": protoc asked plugin to generate a file but " + "did not provide a descriptor for the file: " + << request.file_to_generate(i) << std::endl; return 1; } } @@ -151,7 +152,7 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { } if (!response.SerializeToFileDescriptor(STDOUT_FILENO)) { - cerr << argv[0] << ": Error writing to stdout." << endl; + std::cerr << argv[0] << ": Error writing to stdout." << std::endl; return 1; } diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index f33d716c..fed1726a 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -56,7 +56,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { -1, -1, sizeof(CodeGeneratorRequest), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _internal_metadata_), + -1); CodeGeneratorResponse_descriptor_ = file->message_type(1); static const int CodeGeneratorResponse_offsets_[2] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, error_), @@ -71,7 +72,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { -1, -1, sizeof(CodeGeneratorResponse), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _internal_metadata_), + -1); CodeGeneratorResponse_File_descriptor_ = CodeGeneratorResponse_descriptor_->nested_type(0); static const int CodeGeneratorResponse_File_offsets_[3] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, name_), @@ -87,7 +89,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { -1, -1, sizeof(CodeGeneratorResponse_File), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _internal_metadata_), + -1); } namespace { @@ -137,8 +140,8 @@ void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { "\01324.google.protobuf.compiler.CodeGenerat" "orResponse.File\032>\n\004File\022\014\n\004name\030\001 \001(\t\022\027\n" "\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(\tB" - ",\n\034com.google.protobuf.compilerB\014PluginP" - "rotos", 445); + "7\n\034com.google.protobuf.compilerB\014PluginP" + "rotosZ\tplugin_go", 456); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes); CodeGeneratorRequest::default_instance_ = new CodeGeneratorRequest(); @@ -506,6 +509,147 @@ void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// CodeGeneratorRequest + +// repeated string file_to_generate = 1; + int CodeGeneratorRequest::file_to_generate_size() const { + return file_to_generate_.size(); +} + void CodeGeneratorRequest::clear_file_to_generate() { + file_to_generate_.Clear(); +} + const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) + return file_to_generate_.Get(index); +} + ::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) + return file_to_generate_.Mutable(index); +} + void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) { + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) + file_to_generate_.Mutable(index)->assign(value); +} + void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) { + file_to_generate_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) +} + void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) { + file_to_generate_.Mutable(index)->assign( + reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) +} + ::std::string* CodeGeneratorRequest::add_file_to_generate() { + return file_to_generate_.Add(); +} + void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) { + file_to_generate_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) +} + void CodeGeneratorRequest::add_file_to_generate(const char* value) { + file_to_generate_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) +} + void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) { + file_to_generate_.Add()->assign(reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) +} + const ::google::protobuf::RepeatedPtrField< ::std::string>& +CodeGeneratorRequest::file_to_generate() const { + // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) + return file_to_generate_; +} + ::google::protobuf::RepeatedPtrField< ::std::string>* +CodeGeneratorRequest::mutable_file_to_generate() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) + return &file_to_generate_; +} + +// optional string parameter = 2; + bool CodeGeneratorRequest::has_parameter() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void CodeGeneratorRequest::set_has_parameter() { + _has_bits_[0] |= 0x00000002u; +} + void CodeGeneratorRequest::clear_has_parameter() { + _has_bits_[0] &= ~0x00000002u; +} + void CodeGeneratorRequest::clear_parameter() { + parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_parameter(); +} + const ::std::string& CodeGeneratorRequest::parameter() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter) + return parameter_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorRequest::set_parameter(const ::std::string& value) { + set_has_parameter(); + parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter) +} + void CodeGeneratorRequest::set_parameter(const char* value) { + set_has_parameter(); + parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter) +} + void CodeGeneratorRequest::set_parameter(const char* value, size_t size) { + set_has_parameter(); + parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter) +} + ::std::string* CodeGeneratorRequest::mutable_parameter() { + set_has_parameter(); + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter) + return parameter_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* CodeGeneratorRequest::release_parameter() { + clear_has_parameter(); + return parameter_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) { + if (parameter != NULL) { + set_has_parameter(); + } else { + clear_has_parameter(); + } + parameter_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), parameter); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter) +} + +// repeated .google.protobuf.FileDescriptorProto proto_file = 15; + int CodeGeneratorRequest::proto_file_size() const { + return proto_file_.size(); +} + void CodeGeneratorRequest::clear_proto_file() { + proto_file_.Clear(); +} + const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file) + return proto_file_.Get(index); +} + ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.proto_file) + return proto_file_.Mutable(index); +} + ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() { + // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file) + return proto_file_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& +CodeGeneratorRequest::proto_file() const { + // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file) + return proto_file_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* +CodeGeneratorRequest::mutable_proto_file() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file) + return &proto_file_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -1159,6 +1303,256 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// CodeGeneratorResponse_File + +// optional string name = 1; + bool CodeGeneratorResponse_File::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void CodeGeneratorResponse_File::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} + void CodeGeneratorResponse_File::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} + void CodeGeneratorResponse_File::clear_name() { + name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name(); +} + const ::std::string& CodeGeneratorResponse_File::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name) + return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorResponse_File::set_name(const ::std::string& value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name) +} + void CodeGeneratorResponse_File::set_name(const char* value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name) +} + void CodeGeneratorResponse_File::set_name(const char* value, size_t size) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name) +} + ::std::string* CodeGeneratorResponse_File::mutable_name() { + set_has_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name) + return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* CodeGeneratorResponse_File::release_name() { + clear_has_name(); + return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) { + if (name != NULL) { + set_has_name(); + } else { + clear_has_name(); + } + name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name) +} + +// optional string insertion_point = 2; + bool CodeGeneratorResponse_File::has_insertion_point() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void CodeGeneratorResponse_File::set_has_insertion_point() { + _has_bits_[0] |= 0x00000002u; +} + void CodeGeneratorResponse_File::clear_has_insertion_point() { + _has_bits_[0] &= ~0x00000002u; +} + void CodeGeneratorResponse_File::clear_insertion_point() { + insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_insertion_point(); +} + const ::std::string& CodeGeneratorResponse_File::insertion_point() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) + return insertion_point_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) { + set_has_insertion_point(); + insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) +} + void CodeGeneratorResponse_File::set_insertion_point(const char* value) { + set_has_insertion_point(); + insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) +} + void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) { + set_has_insertion_point(); + insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) +} + ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() { + set_has_insertion_point(); + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) + return insertion_point_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* CodeGeneratorResponse_File::release_insertion_point() { + clear_has_insertion_point(); + return insertion_point_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) { + if (insertion_point != NULL) { + set_has_insertion_point(); + } else { + clear_has_insertion_point(); + } + insertion_point_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), insertion_point); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) +} + +// optional string content = 15; + bool CodeGeneratorResponse_File::has_content() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void CodeGeneratorResponse_File::set_has_content() { + _has_bits_[0] |= 0x00000004u; +} + void CodeGeneratorResponse_File::clear_has_content() { + _has_bits_[0] &= ~0x00000004u; +} + void CodeGeneratorResponse_File::clear_content() { + content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_content(); +} + const ::std::string& CodeGeneratorResponse_File::content() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content) + return content_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorResponse_File::set_content(const ::std::string& value) { + set_has_content(); + content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content) +} + void CodeGeneratorResponse_File::set_content(const char* value) { + set_has_content(); + content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content) +} + void CodeGeneratorResponse_File::set_content(const char* value, size_t size) { + set_has_content(); + content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content) +} + ::std::string* CodeGeneratorResponse_File::mutable_content() { + set_has_content(); + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content) + return content_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* CodeGeneratorResponse_File::release_content() { + clear_has_content(); + return content_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) { + if (content != NULL) { + set_has_content(); + } else { + clear_has_content(); + } + content_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), content); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content) +} + +// ------------------------------------------------------------------- + +// CodeGeneratorResponse + +// optional string error = 1; + bool CodeGeneratorResponse::has_error() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void CodeGeneratorResponse::set_has_error() { + _has_bits_[0] |= 0x00000001u; +} + void CodeGeneratorResponse::clear_has_error() { + _has_bits_[0] &= ~0x00000001u; +} + void CodeGeneratorResponse::clear_error() { + error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_error(); +} + const ::std::string& CodeGeneratorResponse::error() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error) + return error_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorResponse::set_error(const ::std::string& value) { + set_has_error(); + error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error) +} + void CodeGeneratorResponse::set_error(const char* value) { + set_has_error(); + error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error) +} + void CodeGeneratorResponse::set_error(const char* value, size_t size) { + set_has_error(); + error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error) +} + ::std::string* CodeGeneratorResponse::mutable_error() { + set_has_error(); + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error) + return error_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* CodeGeneratorResponse::release_error() { + clear_has_error(); + return error_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorResponse::set_allocated_error(::std::string* error) { + if (error != NULL) { + set_has_error(); + } else { + clear_has_error(); + } + error_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), error); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error) +} + +// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; + int CodeGeneratorResponse::file_size() const { + return file_.size(); +} + void CodeGeneratorResponse::clear_file() { + file_.Clear(); +} + const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file) + return file_.Get(index); +} + ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.file) + return file_.Mutable(index); +} + ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() { + // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file) + return file_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& +CodeGeneratorResponse::file() const { + // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file) + return file_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* +CodeGeneratorResponse::mutable_file() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file) + return &file_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h index 35a0a899..ea48b8b5 100644 --- a/src/google/protobuf/compiler/plugin.pb.h +++ b/src/google/protobuf/compiler/plugin.pb.h @@ -8,12 +8,12 @@ #include <google/protobuf/stubs/common.h> -#if GOOGLE_PROTOBUF_VERSION < 2006000 +#if GOOGLE_PROTOBUF_VERSION < 3000000 #error This file was generated by a newer version of protoc which is #error incompatible with your Protocol Buffer headers. Please update #error your headers. #endif -#if 2006002 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION #error This file was generated by an older version of protoc which is #error incompatible with your Protocol Buffer headers. Please #error regenerate this file with a newer version of protoc. @@ -110,43 +110,43 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message // accessors ------------------------------------------------------- // repeated string file_to_generate = 1; - inline int file_to_generate_size() const; - inline void clear_file_to_generate(); + int file_to_generate_size() const; + void clear_file_to_generate(); static const int kFileToGenerateFieldNumber = 1; - inline const ::std::string& file_to_generate(int index) const; - inline ::std::string* mutable_file_to_generate(int index); - inline void set_file_to_generate(int index, const ::std::string& value); - inline void set_file_to_generate(int index, const char* value); - inline void set_file_to_generate(int index, const char* value, size_t size); - inline ::std::string* add_file_to_generate(); - inline void add_file_to_generate(const ::std::string& value); - inline void add_file_to_generate(const char* value); - inline void add_file_to_generate(const char* value, size_t size); - inline const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const; - inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate(); + const ::std::string& file_to_generate(int index) const; + ::std::string* mutable_file_to_generate(int index); + void set_file_to_generate(int index, const ::std::string& value); + void set_file_to_generate(int index, const char* value); + void set_file_to_generate(int index, const char* value, size_t size); + ::std::string* add_file_to_generate(); + void add_file_to_generate(const ::std::string& value); + void add_file_to_generate(const char* value); + void add_file_to_generate(const char* value, size_t size); + const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const; + ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate(); // optional string parameter = 2; - inline bool has_parameter() const; - inline void clear_parameter(); + bool has_parameter() const; + void clear_parameter(); static const int kParameterFieldNumber = 2; - inline const ::std::string& parameter() const; - inline void set_parameter(const ::std::string& value); - inline void set_parameter(const char* value); - inline void set_parameter(const char* value, size_t size); - inline ::std::string* mutable_parameter(); - inline ::std::string* release_parameter(); - inline void set_allocated_parameter(::std::string* parameter); + const ::std::string& parameter() const; + void set_parameter(const ::std::string& value); + void set_parameter(const char* value); + void set_parameter(const char* value, size_t size); + ::std::string* mutable_parameter(); + ::std::string* release_parameter(); + void set_allocated_parameter(::std::string* parameter); // repeated .google.protobuf.FileDescriptorProto proto_file = 15; - inline int proto_file_size() const; - inline void clear_proto_file(); + int proto_file_size() const; + void clear_proto_file(); static const int kProtoFileFieldNumber = 15; - inline const ::google::protobuf::FileDescriptorProto& proto_file(int index) const; - inline ::google::protobuf::FileDescriptorProto* mutable_proto_file(int index); - inline ::google::protobuf::FileDescriptorProto* add_proto_file(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& + const ::google::protobuf::FileDescriptorProto& proto_file(int index) const; + ::google::protobuf::FileDescriptorProto* mutable_proto_file(int index); + ::google::protobuf::FileDescriptorProto* add_proto_file(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& proto_file() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* mutable_proto_file(); // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest) @@ -234,40 +234,40 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M // accessors ------------------------------------------------------- // optional string name = 1; - inline bool has_name() const; - inline void clear_name(); + bool has_name() const; + void clear_name(); static const int kNameFieldNumber = 1; - inline const ::std::string& name() const; - inline void set_name(const ::std::string& value); - inline void set_name(const char* value); - inline void set_name(const char* value, size_t size); - inline ::std::string* mutable_name(); - inline ::std::string* release_name(); - inline void set_allocated_name(::std::string* name); + const ::std::string& name() const; + void set_name(const ::std::string& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + ::std::string* mutable_name(); + ::std::string* release_name(); + void set_allocated_name(::std::string* name); // optional string insertion_point = 2; - inline bool has_insertion_point() const; - inline void clear_insertion_point(); + bool has_insertion_point() const; + void clear_insertion_point(); static const int kInsertionPointFieldNumber = 2; - inline const ::std::string& insertion_point() const; - inline void set_insertion_point(const ::std::string& value); - inline void set_insertion_point(const char* value); - inline void set_insertion_point(const char* value, size_t size); - inline ::std::string* mutable_insertion_point(); - inline ::std::string* release_insertion_point(); - inline void set_allocated_insertion_point(::std::string* insertion_point); + const ::std::string& insertion_point() const; + void set_insertion_point(const ::std::string& value); + void set_insertion_point(const char* value); + void set_insertion_point(const char* value, size_t size); + ::std::string* mutable_insertion_point(); + ::std::string* release_insertion_point(); + void set_allocated_insertion_point(::std::string* insertion_point); // optional string content = 15; - inline bool has_content() const; - inline void clear_content(); + bool has_content() const; + void clear_content(); static const int kContentFieldNumber = 15; - inline const ::std::string& content() const; - inline void set_content(const ::std::string& value); - inline void set_content(const char* value); - inline void set_content(const char* value, size_t size); - inline ::std::string* mutable_content(); - inline ::std::string* release_content(); - inline void set_allocated_content(::std::string* content); + const ::std::string& content() const; + void set_content(const ::std::string& value); + void set_content(const char* value); + void set_content(const char* value, size_t size); + ::std::string* mutable_content(); + ::std::string* release_content(); + void set_allocated_content(::std::string* content); // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File) private: @@ -360,27 +360,27 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag // accessors ------------------------------------------------------- // optional string error = 1; - inline bool has_error() const; - inline void clear_error(); + bool has_error() const; + void clear_error(); static const int kErrorFieldNumber = 1; - inline const ::std::string& error() const; - inline void set_error(const ::std::string& value); - inline void set_error(const char* value); - inline void set_error(const char* value, size_t size); - inline ::std::string* mutable_error(); - inline ::std::string* release_error(); - inline void set_allocated_error(::std::string* error); + const ::std::string& error() const; + void set_error(const ::std::string& value); + void set_error(const char* value); + void set_error(const char* value, size_t size); + ::std::string* mutable_error(); + ::std::string* release_error(); + void set_allocated_error(::std::string* error); // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; - inline int file_size() const; - inline void clear_file(); + int file_size() const; + void clear_file(); static const int kFileFieldNumber = 15; - inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const; - inline ::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index); - inline ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& + const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const; + ::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index); + ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& file() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* mutable_file(); // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse) @@ -405,6 +405,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag // =================================================================== +#if !PROTOBUF_INLINE_NOT_IN_HEADERS // CodeGeneratorRequest // repeated string file_to_generate = 1; @@ -794,6 +795,7 @@ CodeGeneratorResponse::mutable_file() { return &file_; } +#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) @@ -801,15 +803,6 @@ CodeGeneratorResponse::mutable_file() { } // namespace protobuf } // namespace google -#ifndef SWIG -namespace google { -namespace protobuf { - - -} // namespace protobuf -} // namespace google -#endif // SWIG - // @@protoc_insertion_point(global_scope) #endif // PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto index e627289b..acaee1f4 100644 --- a/src/google/protobuf/compiler/plugin.proto +++ b/src/google/protobuf/compiler/plugin.proto @@ -49,6 +49,8 @@ package google.protobuf.compiler; option java_package = "com.google.protobuf.compiler"; option java_outer_classname = "PluginProtos"; +option go_package = "plugin_go"; + import "google/protobuf/descriptor.proto"; // An encoded CodeGeneratorRequest is written to the plugin's stdin. diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc index e6faf7ef..7b3b5fa3 100644 --- a/src/google/protobuf/compiler/python/python_generator.cc +++ b/src/google/protobuf/compiler/python/python_generator.cc @@ -273,6 +273,19 @@ string StringifyDefaultValue(const FieldDescriptor& field) { return ""; } +string StringifySyntax(FileDescriptor::Syntax syntax) { + switch (syntax) { + case FileDescriptor::SYNTAX_PROTO2: + return "proto2"; + case FileDescriptor::SYNTAX_PROTO3: + return "proto3"; + case FileDescriptor::SYNTAX_UNKNOWN: + default: + GOOGLE_LOG(FATAL) << "Unsupported syntax; this generator only supports proto2 " + "and proto3 syntax."; + return ""; + } +} } // namespace @@ -367,10 +380,12 @@ void Generator::PrintFileDescriptor() const { m["descriptor_name"] = kDescriptorKey; m["name"] = file_->name(); m["package"] = file_->package(); + m["syntax"] = StringifySyntax(file_->syntax()); const char file_descriptor_template[] = "$descriptor_name$ = _descriptor.FileDescriptor(\n" " name='$name$',\n" - " package='$package$',\n"; + " package='$package$',\n" + " syntax='$syntax$',\n"; printer_->Print(m, file_descriptor_template); printer_->Indent(); printer_->Print( @@ -414,7 +429,7 @@ void Generator::PrintTopLevelEnums() const { for (int j = 0; j < enum_descriptor.value_count(); ++j) { const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(j); top_level_enum_values.push_back( - make_pair(value_descriptor.name(), value_descriptor.number())); + std::make_pair(value_descriptor.name(), value_descriptor.number())); } } @@ -580,12 +595,9 @@ void Generator::PrintServiceDescriptor( printer_->Print("])\n\n"); } -void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const { - // Print the service. - printer_->Print("$class_name$ = service_reflection.GeneratedServiceType(" - "'$class_name$', (_service.Service,), dict(\n", - "class_name", descriptor.name()); - printer_->Indent(); + +void Generator::PrintDescriptorKeyAndModuleName( + const ServiceDescriptor& descriptor) const { printer_->Print( "$descriptor_key$ = $descriptor_name$,\n", "descriptor_key", kDescriptorKey, @@ -593,6 +605,15 @@ void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const { printer_->Print( "__module__ = '$module_name$'\n", "module_name", ModuleName(file_->name())); +} + +void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const { + // Print the service. + printer_->Print("$class_name$ = service_reflection.GeneratedServiceType(" + "'$class_name$', (_service.Service,), dict(\n", + "class_name", descriptor.name()); + printer_->Indent(); + Generator::PrintDescriptorKeyAndModuleName(descriptor); printer_->Print("))\n\n"); printer_->Outdent(); } @@ -604,13 +625,7 @@ void Generator::PrintServiceStub(const ServiceDescriptor& descriptor) const { "'$class_name$_Stub', ($class_name$,), dict(\n", "class_name", descriptor.name()); printer_->Indent(); - printer_->Print( - "$descriptor_key$ = $descriptor_name$,\n", - "descriptor_key", kDescriptorKey, - "descriptor_name", ModuleLevelServiceDescriptorName(descriptor)); - printer_->Print( - "__module__ = '$module_name$'\n", - "module_name", ModuleName(file_->name())); + Generator::PrintDescriptorKeyAndModuleName(descriptor); printer_->Print("))\n\n"); printer_->Outdent(); } @@ -665,10 +680,12 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { message_descriptor.options().SerializeToString(&options_string); printer_->Print( "options=$options_value$,\n" - "is_extendable=$extendable$", + "is_extendable=$extendable$,\n" + "syntax='$syntax$'", "options_value", OptionsValue("MessageOptions", options_string), "extendable", message_descriptor.extension_range_count() > 0 ? - "True" : "False"); + "True" : "False", + "syntax", StringifySyntax(message_descriptor.file()->syntax())); printer_->Print(",\n"); // Extension ranges diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h index 7e8f58e5..2ddac601 100644 --- a/src/google/protobuf/compiler/python/python_generator.h +++ b/src/google/protobuf/compiler/python/python_generator.h @@ -127,6 +127,8 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void PrintServiceDescriptor(const ServiceDescriptor& descriptor) const; void PrintServiceClass(const ServiceDescriptor& descriptor) const; void PrintServiceStub(const ServiceDescriptor& descriptor) const; + void PrintDescriptorKeyAndModuleName( + const ServiceDescriptor& descriptor) const ; void PrintEnumValueDescriptor(const EnumValueDescriptor& descriptor) const; string OptionsValue(const string& class_name, diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc new file mode 100644 index 00000000..a9b6837e --- /dev/null +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -0,0 +1,393 @@ +// 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 <sstream> + +#include <google/protobuf/compiler/code_generator.h> +#include <google/protobuf/compiler/plugin.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/io/zero_copy_stream.h> + +#include <google/protobuf/compiler/ruby/ruby_generator.h> + +using google::protobuf::internal::scoped_ptr; + +namespace google { +namespace protobuf { +namespace compiler { +namespace ruby { + +// Forward decls. +std::string IntToString(uint32 value); +std::string StripDotProto(const std::string& proto_file); +std::string LabelForField(google::protobuf::FieldDescriptor* field); +std::string TypeName(google::protobuf::FieldDescriptor* field); +void GenerateMessage(const google::protobuf::Descriptor* message, + google::protobuf::io::Printer* printer); +void GenerateEnum(const google::protobuf::EnumDescriptor* en, + google::protobuf::io::Printer* printer); +void GenerateMessageAssignment( + const std::string& prefix, + const google::protobuf::Descriptor* message, + google::protobuf::io::Printer* printer); +void GenerateEnumAssignment( + const std::string& prefix, + const google::protobuf::EnumDescriptor* en, + google::protobuf::io::Printer* printer); + +std::string IntToString(uint32 value) { + std::ostringstream os; + os << value; + return os.str(); +} + +std::string StripDotProto(const std::string& proto_file) { + int lastindex = proto_file.find_last_of("."); + return proto_file.substr(0, lastindex); +} + +std::string LabelForField(const google::protobuf::FieldDescriptor* field) { + switch (field->label()) { + case FieldDescriptor::LABEL_OPTIONAL: return "optional"; + case FieldDescriptor::LABEL_REQUIRED: return "required"; + case FieldDescriptor::LABEL_REPEATED: return "repeated"; + default: assert(false); return ""; + } +} + +std::string TypeName(const google::protobuf::FieldDescriptor* field) { + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: return "int32"; + case FieldDescriptor::CPPTYPE_INT64: return "int64"; + case FieldDescriptor::CPPTYPE_UINT32: return "uint32"; + case FieldDescriptor::CPPTYPE_UINT64: return "uint64"; + case FieldDescriptor::CPPTYPE_DOUBLE: return "double"; + case FieldDescriptor::CPPTYPE_FLOAT: return "float"; + case FieldDescriptor::CPPTYPE_BOOL: return "bool"; + case FieldDescriptor::CPPTYPE_ENUM: return "enum"; + case FieldDescriptor::CPPTYPE_STRING: return "string"; + case FieldDescriptor::CPPTYPE_MESSAGE: return "message"; + default: assert(false); return ""; + } +} + +void GenerateField(const google::protobuf::FieldDescriptor* field, + google::protobuf::io::Printer* printer) { + + if (field->is_map()) { + const FieldDescriptor* key_field = + field->message_type()->FindFieldByNumber(1); + const FieldDescriptor* value_field = + field->message_type()->FindFieldByNumber(2); + + printer->Print( + "map :$name$, :$key_type$, :$value_type$, $number$", + "name", field->name(), + "key_type", TypeName(key_field), + "value_type", TypeName(value_field), + "number", IntToString(field->number())); + + if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + printer->Print( + ", \"$subtype$\"\n", + "subtype", value_field->message_type()->full_name()); + } else if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + printer->Print( + ", \"$subtype$\"\n", + "subtype", value_field->enum_type()->full_name()); + } else { + printer->Print("\n"); + } + } else { + + printer->Print( + "$label$ :$name$, ", + "label", LabelForField(field), + "name", field->name()); + printer->Print( + ":$type$, $number$", + "type", TypeName(field), + "number", IntToString(field->number())); + + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + printer->Print( + ", \"$subtype$\"\n", + "subtype", field->message_type()->full_name()); + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + printer->Print( + ", \"$subtype$\"\n", + "subtype", field->enum_type()->full_name()); + } else { + printer->Print("\n"); + } + } +} + +void GenerateOneof(const google::protobuf::OneofDescriptor* oneof, + google::protobuf::io::Printer* printer) { + printer->Print( + "oneof :$name$ do\n", + "name", oneof->name()); + printer->Indent(); + + for (int i = 0; i < oneof->field_count(); i++) { + const FieldDescriptor* field = oneof->field(i); + GenerateField(field, printer); + } + + printer->Outdent(); + printer->Print("end\n"); +} + +void GenerateMessage(const google::protobuf::Descriptor* message, + google::protobuf::io::Printer* printer) { + + // Don't generate MapEntry messages -- we use the Ruby extension's native + // support for map fields instead. + if (message->options().map_entry()) { + return; + } + + printer->Print( + "add_message \"$name$\" do\n", + "name", message->full_name()); + printer->Indent(); + + for (int i = 0; i < message->field_count(); i++) { + const FieldDescriptor* field = message->field(i); + if (!field->containing_oneof()) { + GenerateField(field, printer); + } + } + + for (int i = 0; i < message->oneof_decl_count(); i++) { + const OneofDescriptor* oneof = message->oneof_decl(i); + GenerateOneof(oneof, printer); + } + + printer->Outdent(); + printer->Print("end\n"); + + for (int i = 0; i < message->nested_type_count(); i++) { + GenerateMessage(message->nested_type(i), printer); + } + for (int i = 0; i < message->enum_type_count(); i++) { + GenerateEnum(message->enum_type(i), printer); + } +} + +void GenerateEnum(const google::protobuf::EnumDescriptor* en, + google::protobuf::io::Printer* printer) { + printer->Print( + "add_enum \"$name$\" do\n", + "name", en->full_name()); + printer->Indent(); + + for (int i = 0; i < en->value_count(); i++) { + const EnumValueDescriptor* value = en->value(i); + printer->Print( + "value :$name$, $number$\n", + "name", value->name(), + "number", IntToString(value->number())); + } + + printer->Outdent(); + printer->Print( + "end\n"); +} + +// Module names, class names, and enum value names need to be Ruby constants, +// which must start with a capital letter. +std::string RubifyConstant(const std::string& name) { + std::string ret = name; + if (!ret.empty()) { + if (ret[0] >= 'a' && ret[0] <= 'z') { + // If it starts with a lowercase letter, capitalize it. + ret[0] = ret[0] - 'a' + 'A'; + } else if (ret[0] < 'A' || ret[0] > 'Z') { + // Otherwise (e.g. if it begins with an underscore), we need to come up + // with some prefix that starts with a capital letter. We could be smarter + // here, e.g. try to strip leading underscores, but this may cause other + // problems if the user really intended the name. So let's just prepend a + // well-known suffix. + ret = "PB_" + ret; + } + } + return ret; +} + +void GenerateMessageAssignment( + const std::string& prefix, + const google::protobuf::Descriptor* message, + google::protobuf::io::Printer* printer) { + + // Don't generate MapEntry messages -- we use the Ruby extension's native + // support for map fields instead. + if (message->options().map_entry()) { + return; + } + + printer->Print( + "$prefix$$name$ = ", + "prefix", prefix, + "name", RubifyConstant(message->name())); + printer->Print( + "Google::Protobuf::DescriptorPool.generated_pool." + "lookup(\"$full_name$\").msgclass\n", + "full_name", message->full_name()); + + std::string nested_prefix = prefix + message->name() + "::"; + for (int i = 0; i < message->nested_type_count(); i++) { + GenerateMessageAssignment(nested_prefix, message->nested_type(i), printer); + } + for (int i = 0; i < message->enum_type_count(); i++) { + GenerateEnumAssignment(nested_prefix, message->enum_type(i), printer); + } +} + +void GenerateEnumAssignment( + const std::string& prefix, + const google::protobuf::EnumDescriptor* en, + google::protobuf::io::Printer* printer) { + printer->Print( + "$prefix$$name$ = ", + "prefix", prefix, + "name", RubifyConstant(en->name())); + printer->Print( + "Google::Protobuf::DescriptorPool.generated_pool." + "lookup(\"$full_name$\").enummodule\n", + "full_name", en->full_name()); +} + +int GeneratePackageModules( + std::string package_name, + google::protobuf::io::Printer* printer) { + int levels = 0; + while (!package_name.empty()) { + size_t dot_index = package_name.find("."); + string component; + if (dot_index == string::npos) { + component = package_name; + package_name = ""; + } else { + component = package_name.substr(0, dot_index); + package_name = package_name.substr(dot_index + 1); + } + component = RubifyConstant(component); + printer->Print( + "module $name$\n", + "name", component); + printer->Indent(); + levels++; + } + return levels; +} + +void EndPackageModules( + int levels, + google::protobuf::io::Printer* printer) { + while (levels > 0) { + levels--; + printer->Outdent(); + printer->Print( + "end\n"); + } +} + +void GenerateFile(const google::protobuf::FileDescriptor* file, + google::protobuf::io::Printer* printer) { + printer->Print( + "# Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "# source: $filename$\n" + "\n", + "filename", file->name()); + + printer->Print( + "require 'google/protobuf'\n\n"); + + for (int i = 0; i < file->dependency_count(); i++) { + const std::string& name = file->dependency(i)->name(); + printer->Print( + "require '$name$'\n", "name", StripDotProto(name)); + } + + printer->Print( + "Google::Protobuf::DescriptorPool.generated_pool.build do\n"); + printer->Indent(); + for (int i = 0; i < file->message_type_count(); i++) { + GenerateMessage(file->message_type(i), printer); + } + for (int i = 0; i < file->enum_type_count(); i++) { + GenerateEnum(file->enum_type(i), printer); + } + printer->Outdent(); + printer->Print( + "end\n\n"); + + int levels = GeneratePackageModules(file->package(), printer); + for (int i = 0; i < file->message_type_count(); i++) { + GenerateMessageAssignment("", file->message_type(i), printer); + } + for (int i = 0; i < file->enum_type_count(); i++) { + GenerateEnumAssignment("", file->enum_type(i), printer); + } + EndPackageModules(levels, printer); +} + +bool Generator::Generate( + const FileDescriptor* file, + const string& parameter, + GeneratorContext* generator_context, + string* error) const { + + if (file->syntax() != FileDescriptor::SYNTAX_PROTO3) { + *error = + "Can only generate Ruby code for proto3 .proto files.\n" + "Please add 'syntax = \"proto3\";' to the top of your .proto file.\n"; + return false; + } + + std::string filename = + StripDotProto(file->name()) + ".rb"; + scoped_ptr<io::ZeroCopyOutputStream> output( + generator_context->Open(filename)); + io::Printer printer(output.get(), '$'); + + GenerateFile(file, &printer); + + return true; +} + +} // namespace ruby +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.h b/src/google/protobuf/compiler/ruby/ruby_generator.h new file mode 100644 index 00000000..75555c31 --- /dev/null +++ b/src/google/protobuf/compiler/ruby/ruby_generator.h @@ -0,0 +1,58 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_RUBY_GENERATOR_H__ +#define GOOGLE_PROTOBUF_COMPILER_RUBY_GENERATOR_H__ + +#include <string> + +#include <google/protobuf/compiler/code_generator.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace ruby { + +class LIBPROTOC_EXPORT Generator + : public google::protobuf::compiler::CodeGenerator { + virtual bool Generate( + const FileDescriptor* file, + const string& parameter, + GeneratorContext* generator_context, + string* error) const; +}; + +} // namespace ruby +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_RUBY_GENERATOR_H__ + diff --git a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc new file mode 100644 index 00000000..e35ca695 --- /dev/null +++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc @@ -0,0 +1,119 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2014 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <memory> + +#include <google/protobuf/compiler/ruby/ruby_generator.h> +#include <google/protobuf/compiler/command_line_interface.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/io/printer.h> + +#include <google/protobuf/testing/googletest.h> +#include <gtest/gtest.h> +#include <google/protobuf/testing/file.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace ruby { +namespace { + +string FindRubyTestDir() { + // Inspired by TestSourceDir() in src/google/protobuf/testing/googletest.cc. + string prefix = "."; + while (!File::Exists(prefix + "/ruby/tests")) { + if (!File::Exists(prefix)) { + GOOGLE_LOG(FATAL) + << "Could not find Ruby test directory. Please run tests from " + "somewhere within the protobuf source package."; + } + prefix += "/.."; + } + return prefix + "/ruby/tests"; +} + +// This test is a simple golden-file test over the output of the Ruby code +// generator. When we make changes to the Ruby extension and alter the Ruby code +// generator to use those changes, we should (i) manually test the output of the +// code generator with the extension, and (ii) update the golden output above. +// Some day, we may integrate build systems between protoc and the language +// extensions to the point where we can do this test in a more automated way. + +TEST(RubyGeneratorTest, GeneratorTest) { + string ruby_tests = FindRubyTestDir(); + + google::protobuf::compiler::CommandLineInterface cli; + cli.SetInputsAreProtoPathRelative(true); + + ruby::Generator ruby_generator; + cli.RegisterGenerator("--ruby_out", &ruby_generator, ""); + + // Copy generated_code.proto to the temporary test directory. + string test_input; + GOOGLE_CHECK_OK(File::GetContents( + ruby_tests + "/generated_code.proto", + &test_input, + true)); + GOOGLE_CHECK_OK(File::SetContents( + TestTempDir() + "/generated_code.proto", + test_input, + true)); + + // Invoke the proto compiler (we will be inside TestTempDir() at this point). + string ruby_out = "--ruby_out=" + TestTempDir(); + string proto_path = "--proto_path=" + TestTempDir(); + const char* argv[] = { + "protoc", + ruby_out.c_str(), + proto_path.c_str(), + "generated_code.proto", + }; + + EXPECT_EQ(0, cli.Run(4, argv)); + + // Load the generated output and compare to the expected result. + string output; + GOOGLE_CHECK_OK(File::GetContents( + TestTempDir() + "/generated_code.rb", + &output, + true)); + string expected_output; + GOOGLE_CHECK_OK(File::GetContents( + ruby_tests + "/generated_code.rb", + &expected_output, + true)); + EXPECT_EQ(expected_output, output); +} + +} // namespace +} // namespace ruby +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index 7bc172a8..bfdacd95 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -144,6 +144,8 @@ const char* FileDescriptor::SyntaxName(FileDescriptor::Syntax syntax) { case SYNTAX_UNKNOWN: return "unknown"; } + GOOGLE_LOG(FATAL) << "can't reach here."; + return NULL; } static const char * const kNonLinkedWeakMessageReplacementName = "google.protobuf.Empty"; @@ -343,6 +345,10 @@ typedef hash_map<string, const SourceCodeInfo_Location*> LocationsByPathMap; set<string>* allowed_proto3_extendees_ = NULL; GOOGLE_PROTOBUF_DECLARE_ONCE(allowed_proto3_extendees_init_); +void DeleteAllowedProto3Extendee() { + delete allowed_proto3_extendees_; +} + void InitAllowedProto3Extendee() { allowed_proto3_extendees_ = new set<string>; allowed_proto3_extendees_->insert("google.protobuf.FileOptions"); @@ -352,6 +358,7 @@ void InitAllowedProto3Extendee() { allowed_proto3_extendees_->insert("google.protobuf.EnumValueOptions"); allowed_proto3_extendees_->insert("google.protobuf.ServiceOptions"); allowed_proto3_extendees_->insert("google.protobuf.MethodOptions"); + google::protobuf::internal::OnShutdown(&DeleteAllowedProto3Extendee); } // Checks whether the extendee type is allowed in proto3. @@ -776,7 +783,7 @@ inline const FileDescriptor* DescriptorPool::Tables::FindFile( inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber( const Descriptor* parent, int number) const { - return FindPtrOrNull(fields_by_number_, make_pair(parent, number)); + return FindPtrOrNull(fields_by_number_, std::make_pair(parent, number)); } inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName( @@ -793,7 +800,7 @@ inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName( inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber( const EnumDescriptor* parent, int number) const { - return FindPtrOrNull(enum_values_by_number_, make_pair(parent, number)); + return FindPtrOrNull(enum_values_by_number_, std::make_pair(parent, number)); } inline const EnumValueDescriptor* @@ -801,8 +808,8 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown( const EnumDescriptor* parent, int number) const { // First try, with map of compiled-in values. { - const EnumValueDescriptor* desc = FindPtrOrNull( - enum_values_by_number_, make_pair(parent, number)); + const EnumValueDescriptor* desc = + FindPtrOrNull(enum_values_by_number_, std::make_pair(parent, number)); if (desc != NULL) { return desc; } @@ -811,7 +818,7 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown( { ReaderMutexLock l(&unknown_enum_values_mu_); const EnumValueDescriptor* desc = FindPtrOrNull( - unknown_enum_values_by_number_, make_pair(parent, number)); + unknown_enum_values_by_number_, std::make_pair(parent, number)); if (desc != NULL) { return desc; } @@ -821,7 +828,7 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown( { WriterMutexLock l(&unknown_enum_values_mu_); const EnumValueDescriptor* desc = FindPtrOrNull( - unknown_enum_values_by_number_, make_pair(parent, number)); + unknown_enum_values_by_number_, std::make_pair(parent, number)); if (desc != NULL) { return desc; } @@ -843,8 +850,7 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown( result->type_ = parent; result->options_ = &EnumValueOptions::default_instance(); InsertIfNotPresent(&unknown_enum_values_by_number_, - make_pair(parent, number), - result); + std::make_pair(parent, number), result); return result; } } @@ -852,13 +858,13 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown( inline const FieldDescriptor* DescriptorPool::Tables::FindExtension( const Descriptor* extendee, int number) { - return FindPtrOrNull(extensions_, make_pair(extendee, number)); + return FindPtrOrNull(extensions_, std::make_pair(extendee, number)); } inline void DescriptorPool::Tables::FindAllExtensions( const Descriptor* extendee, vector<const FieldDescriptor*>* out) const { ExtensionsGroupedByDescriptorMap::const_iterator it = - extensions_.lower_bound(make_pair(extendee, 0)); + extensions_.lower_bound(std::make_pair(extendee, 0)); for (; it != extensions_.end() && it->first.first == extendee; ++it) { out->push_back(it->second); } @@ -986,7 +992,7 @@ void FileDescriptorTables::BuildLocationsByPath( const SourceCodeInfo_Location* FileDescriptorTables::GetSourceLocation( const vector<int>& path, const SourceCodeInfo* info) const { pair<const FileDescriptorTables*, const SourceCodeInfo*> p( - make_pair(this, info)); + std::make_pair(this, info)); locations_by_path_once_.Init(&FileDescriptorTables::BuildLocationsByPath, &p); return FindPtrOrNull(locations_by_path_, Join(path, ",")); } @@ -1922,9 +1928,9 @@ bool FormatLineOptions(int depth, const Message &options, string *output) { return !all_options.empty(); } -template<typename DescType> class SourceLocationCommentPrinter { public: + template<typename DescType> SourceLocationCommentPrinter(const DescType* desc, const string& prefix, const DebugStringOptions& options) @@ -1934,9 +1940,27 @@ class SourceLocationCommentPrinter { have_source_loc_ = options.include_comments && desc->GetSourceLocation(&source_loc_); } + SourceLocationCommentPrinter(const FileDescriptor* file, + const vector<int>& path, + const string& prefix, + const DebugStringOptions& options) + : options_(options), prefix_(prefix) { + // Perform the SourceLocation lookup only if we're including user comments, + // because the lookup is fairly expensive. + have_source_loc_ = options.include_comments && + file->GetSourceLocation(path, &source_loc_); + } void AddPreComment(string* output) { - if (have_source_loc_ && source_loc_.leading_comments.size() > 0) { - *output += FormatComment(source_loc_.leading_comments); + if (have_source_loc_) { + // Detached leading comments. + for (int i = 0 ; i < source_loc_.leading_detached_comments.size(); ++i) { + *output += FormatComment(source_loc_.leading_detached_comments[i]); + *output += "\n"; + } + // Attached leading comments. + if (!source_loc_.leading_comments.empty()) { + *output += FormatComment(source_loc_.leading_comments); + } } } void AddPostComment(string* output) { @@ -1960,7 +1984,6 @@ class SourceLocationCommentPrinter { } private: - const DescType* desc_; bool have_source_loc_; SourceLocation source_loc_; DebugStringOptions options_; @@ -1977,10 +2000,18 @@ string FileDescriptor::DebugString() const { string FileDescriptor::DebugStringWithOptions( const DebugStringOptions& debug_string_options) const { string contents; - strings::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n", - SyntaxName(syntax())); + { + vector<int> path; + path.push_back(FileDescriptorProto::kSyntaxFieldNumber); + SourceLocationCommentPrinter syntax_comment( + this, path, "", debug_string_options); + syntax_comment.AddPreComment(&contents); + strings::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n", + SyntaxName(syntax())); + syntax_comment.AddPostComment(&contents); + } - SourceLocationCommentPrinter<FileDescriptor> + SourceLocationCommentPrinter comment_printer(this, "", debug_string_options); comment_printer.AddPreComment(&contents); @@ -2005,7 +2036,13 @@ string FileDescriptor::DebugStringWithOptions( } if (!package().empty()) { + vector<int> path; + path.push_back(FileDescriptorProto::kPackageFieldNumber); + SourceLocationCommentPrinter package_comment( + this, path, "", debug_string_options); + package_comment.AddPreComment(&contents); strings::SubstituteAndAppend(&contents, "package $0;\n\n", package()); + package_comment.AddPostComment(&contents); } if (FormatLineOptions(0, options(), &contents)) { @@ -2080,7 +2117,7 @@ void Descriptor::DebugString(int depth, string *contents, string prefix(depth * 2, ' '); ++depth; - SourceLocationCommentPrinter<Descriptor> + SourceLocationCommentPrinter comment_printer(this, prefix, debug_string_options); comment_printer.AddPreComment(contents); @@ -2210,7 +2247,7 @@ void FieldDescriptor::DebugString(int depth, label.push_back(' '); } - SourceLocationCommentPrinter<FieldDescriptor> + SourceLocationCommentPrinter comment_printer(this, prefix, debug_string_options); comment_printer.AddPreComment(contents); @@ -2267,7 +2304,7 @@ void OneofDescriptor::DebugString(int depth, string* contents, debug_string_options) const { string prefix(depth * 2, ' '); ++depth; - SourceLocationCommentPrinter<OneofDescriptor> + SourceLocationCommentPrinter comment_printer(this, prefix, debug_string_options); comment_printer.AddPreComment(contents); strings::SubstituteAndAppend( @@ -2298,7 +2335,7 @@ void EnumDescriptor::DebugString(int depth, string *contents, string prefix(depth * 2, ' '); ++depth; - SourceLocationCommentPrinter<EnumDescriptor> + SourceLocationCommentPrinter comment_printer(this, prefix, debug_string_options); comment_printer.AddPreComment(contents); @@ -2332,7 +2369,7 @@ void EnumValueDescriptor::DebugString(int depth, string *contents, debug_string_options) const { string prefix(depth * 2, ' '); - SourceLocationCommentPrinter<EnumValueDescriptor> + SourceLocationCommentPrinter comment_printer(this, prefix, debug_string_options); comment_printer.AddPreComment(contents); @@ -2363,7 +2400,7 @@ string ServiceDescriptor::DebugStringWithOptions( void ServiceDescriptor::DebugString(string *contents, const DebugStringOptions& debug_string_options) const { - SourceLocationCommentPrinter<ServiceDescriptor> + SourceLocationCommentPrinter comment_printer(this, /* prefix */ "", debug_string_options); comment_printer.AddPreComment(contents); @@ -2398,7 +2435,7 @@ void MethodDescriptor::DebugString(int depth, string *contents, string prefix(depth * 2, ' '); ++depth; - SourceLocationCommentPrinter<MethodDescriptor> + SourceLocationCommentPrinter comment_printer(this, prefix, debug_string_options); comment_printer.AddPreComment(contents); @@ -2438,6 +2475,9 @@ bool FileDescriptor::GetSourceLocation(const vector<int>& path, out_location->leading_comments = loc->leading_comments(); out_location->trailing_comments = loc->trailing_comments(); + out_location->leading_detached_comments.assign( + loc->leading_detached_comments().begin(), + loc->leading_detached_comments().end()); return true; } } @@ -3690,7 +3730,6 @@ const FileDescriptor* DescriptorBuilder::BuildFile( "Unrecognized syntax: " + proto.syntax()); } - result->name_ = tables_->AllocateString(proto.name()); if (proto.has_package()) { result->package_ = tables_->AllocateString(proto.package()); @@ -5103,7 +5142,7 @@ bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field, case FieldDescriptor::TYPE_SFIXED64: // Legal cases break; - // Do not add a default, so that the compiler will complian when new types + // Do not add a default, so that the compiler will complain when new types // are added. } @@ -5116,7 +5155,7 @@ void DescriptorBuilder::DetectMapConflicts(const Descriptor* message, for (int i = 0; i < message->nested_type_count(); ++i) { const Descriptor* nested = message->nested_type(i); pair<map<string, const Descriptor*>::iterator, bool> result = - seen_types.insert(make_pair(nested->name(), nested)); + seen_types.insert(std::make_pair(nested->name(), nested)); if (!result.second) { if (result.first->second->options().map_entry() || nested->options().map_entry()) { diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h index 52df47f3..0e264f54 100644 --- a/src/google/protobuf/descriptor.h +++ b/src/google/protobuf/descriptor.h @@ -117,8 +117,10 @@ struct SourceLocation { int end_column; // Doc comments found at the source location. + // See the comments in SourceCodeInfo.Location (descriptor.proto) for details. string leading_comments; string trailing_comments; + vector<string> leading_detached_comments; }; // Options when generating machine-parsable output from a descriptor with @@ -312,7 +314,7 @@ class LIBPROTOBUF_EXPORT Descriptor { // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. - void GetLocationPath(vector<int>* output) const; + void GetLocationPath(std::vector<int>* output) const; const string* name_; const string* full_name_; @@ -594,7 +596,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. - void GetLocationPath(vector<int>* output) const; + void GetLocationPath(std::vector<int>* output) const; const string* name_; const string* full_name_; @@ -688,7 +690,7 @@ class LIBPROTOBUF_EXPORT OneofDescriptor { // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. - void GetLocationPath(vector<int>* output) const; + void GetLocationPath(std::vector<int>* output) const; const string* name_; const string* full_name_; @@ -790,7 +792,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptor { // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. - void GetLocationPath(vector<int>* output) const; + void GetLocationPath(std::vector<int>* output) const; const string* name_; const string* full_name_; @@ -874,7 +876,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptor { // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. - void GetLocationPath(vector<int>* output) const; + void GetLocationPath(std::vector<int>* output) const; const string* name_; const string* full_name_; @@ -949,7 +951,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptor { // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. - void GetLocationPath(vector<int>* output) const; + void GetLocationPath(std::vector<int>* output) const; const string* name_; const string* full_name_; @@ -1028,7 +1030,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptor { // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. - void GetLocationPath(vector<int>* output) const; + void GetLocationPath(std::vector<int>* output) const; const string* name_; const string* full_name_; @@ -1173,17 +1175,15 @@ class LIBPROTOBUF_EXPORT FileDescriptor { // this file declaration (namely, the empty path). bool GetSourceLocation(SourceLocation* out_location) const; - private: - // Source Location --------------------------------------------------- - // Updates |*out_location| to the source location of the complete // extent of the declaration or declaration-part denoted by |path|. // Returns false and leaves |*out_location| unchanged iff location // information was not available. (See SourceCodeInfo for // description of path encoding.) - bool GetSourceLocation(const vector<int>& path, + bool GetSourceLocation(const std::vector<int>& path, SourceLocation* out_location) const; + private: typedef FileOptions OptionsType; const string* name_; @@ -1326,7 +1326,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // found: extensions defined in the fallback database might not be found // depending on the database implementation. void FindAllExtensions(const Descriptor* extendee, - vector<const FieldDescriptor*>* out) const; + std::vector<const FieldDescriptor*>* out) const; // Building descriptors -------------------------------------------- diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index df214d44..c201136e 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -111,7 +111,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, -1, sizeof(FileDescriptorSet), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, _internal_metadata_), + -1); FileDescriptorProto_descriptor_ = file->message_type(1); static const int FileDescriptorProto_offsets_[12] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, name_), @@ -136,7 +137,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, -1, sizeof(FileDescriptorProto), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, _internal_metadata_), + -1); DescriptorProto_descriptor_ = file->message_type(2); static const int DescriptorProto_offsets_[8] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, name_), @@ -157,7 +159,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, -1, sizeof(DescriptorProto), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, _internal_metadata_), + -1); DescriptorProto_ExtensionRange_descriptor_ = DescriptorProto_descriptor_->nested_type(0); static const int DescriptorProto_ExtensionRange_offsets_[2] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, start_), @@ -172,7 +175,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, -1, sizeof(DescriptorProto_ExtensionRange), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, _internal_metadata_), + -1); FieldDescriptorProto_descriptor_ = file->message_type(3); static const int FieldDescriptorProto_offsets_[9] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, name_), @@ -194,7 +198,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, -1, sizeof(FieldDescriptorProto), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, _internal_metadata_), + -1); FieldDescriptorProto_Type_descriptor_ = FieldDescriptorProto_descriptor_->enum_type(0); FieldDescriptorProto_Label_descriptor_ = FieldDescriptorProto_descriptor_->enum_type(1); OneofDescriptorProto_descriptor_ = file->message_type(4); @@ -210,7 +215,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, -1, sizeof(OneofDescriptorProto), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofDescriptorProto, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofDescriptorProto, _internal_metadata_), + -1); EnumDescriptorProto_descriptor_ = file->message_type(5); static const int EnumDescriptorProto_offsets_[3] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, name_), @@ -226,7 +232,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, -1, sizeof(EnumDescriptorProto), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, _internal_metadata_), + -1); EnumValueDescriptorProto_descriptor_ = file->message_type(6); static const int EnumValueDescriptorProto_offsets_[3] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, name_), @@ -242,7 +249,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, -1, sizeof(EnumValueDescriptorProto), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, _internal_metadata_), + -1); ServiceDescriptorProto_descriptor_ = file->message_type(7); static const int ServiceDescriptorProto_offsets_[3] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, name_), @@ -258,7 +266,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, -1, sizeof(ServiceDescriptorProto), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, _internal_metadata_), + -1); MethodDescriptorProto_descriptor_ = file->message_type(8); static const int MethodDescriptorProto_offsets_[6] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, name_), @@ -277,9 +286,10 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, -1, sizeof(MethodDescriptorProto), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _internal_metadata_), + -1); FileOptions_descriptor_ = file->message_type(9); - static const int FileOptions_offsets_[13] = { + static const int FileOptions_offsets_[14] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_multiple_files_), @@ -292,6 +302,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, py_generic_services_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, deprecated_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_enable_arenas_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, objc_class_prefix_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, uninterpreted_option_), }; FileOptions_reflection_ = @@ -303,7 +314,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _extensions_), sizeof(FileOptions), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _internal_metadata_), + -1); FileOptions_OptimizeMode_descriptor_ = FileOptions_descriptor_->enum_type(0); MessageOptions_descriptor_ = file->message_type(10); static const int MessageOptions_offsets_[5] = { @@ -322,7 +334,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _extensions_), sizeof(MessageOptions), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _internal_metadata_), + -1); FieldOptions_descriptor_ = file->message_type(11); static const int FieldOptions_offsets_[6] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, ctype_), @@ -341,7 +354,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _extensions_), sizeof(FieldOptions), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _internal_metadata_), + -1); FieldOptions_CType_descriptor_ = FieldOptions_descriptor_->enum_type(0); EnumOptions_descriptor_ = file->message_type(12); static const int EnumOptions_offsets_[3] = { @@ -358,7 +372,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _extensions_), sizeof(EnumOptions), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _internal_metadata_), + -1); EnumValueOptions_descriptor_ = file->message_type(13); static const int EnumValueOptions_offsets_[2] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, deprecated_), @@ -373,7 +388,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _extensions_), sizeof(EnumValueOptions), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _internal_metadata_), + -1); ServiceOptions_descriptor_ = file->message_type(14); static const int ServiceOptions_offsets_[2] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, deprecated_), @@ -388,7 +404,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _extensions_), sizeof(ServiceOptions), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _internal_metadata_), + -1); MethodOptions_descriptor_ = file->message_type(15); static const int MethodOptions_offsets_[2] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, deprecated_), @@ -403,7 +420,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _extensions_), sizeof(MethodOptions), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _internal_metadata_), + -1); UninterpretedOption_descriptor_ = file->message_type(16); static const int UninterpretedOption_offsets_[7] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, name_), @@ -423,7 +441,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, -1, sizeof(UninterpretedOption), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, _internal_metadata_), + -1); UninterpretedOption_NamePart_descriptor_ = UninterpretedOption_descriptor_->nested_type(0); static const int UninterpretedOption_NamePart_offsets_[2] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, name_part_), @@ -438,7 +457,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, -1, sizeof(UninterpretedOption_NamePart), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, _internal_metadata_), + -1); SourceCodeInfo_descriptor_ = file->message_type(17); static const int SourceCodeInfo_offsets_[1] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, location_), @@ -452,13 +472,15 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, -1, sizeof(SourceCodeInfo), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _internal_metadata_), + -1); SourceCodeInfo_Location_descriptor_ = SourceCodeInfo_descriptor_->nested_type(0); - static const int SourceCodeInfo_Location_offsets_[4] = { + static const int SourceCodeInfo_Location_offsets_[5] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, path_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, span_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, leading_comments_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, trailing_comments_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, leading_detached_comments_), }; SourceCodeInfo_Location_reflection_ = ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection( @@ -469,7 +491,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { -1, -1, sizeof(SourceCodeInfo_Location), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _internal_metadata_)); + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _internal_metadata_), + -1); } namespace { @@ -640,7 +663,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "t_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.p" "rotobuf.MethodOptions\022\037\n\020client_streamin" "g\030\005 \001(\010:\005false\022\037\n\020server_streaming\030\006 \001(\010" - ":\005false\"\314\004\n\013FileOptions\022\024\n\014java_package\030" + ":\005false\"\347\004\n\013FileOptions\022\024\n\014java_package\030" "\001 \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023j" "ava_multiple_files\030\n \001(\010:\005false\022,\n\035java_" "generate_equals_and_hash\030\024 \001(\010:\005false\022%\n" @@ -651,49 +674,51 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "alse\022$\n\025java_generic_services\030\021 \001(\010:\005fal" "se\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022\031" "\n\ndeprecated\030\027 \001(\010:\005false\022\037\n\020cc_enable_a" - "renas\030\037 \001(\010:\005false\022C\n\024uninterpreted_opti" + "renas\030\037 \001(\010:\005false\022\031\n\021objc_class_prefix\030" + "$ \001(\t\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.g" + "oogle.protobuf.UninterpretedOption\":\n\014Op" + "timizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014" + "LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016MessageOpt" + "ions\022&\n\027message_set_wire_format\030\001 \001(\010:\005f" + "alse\022.\n\037no_standard_descriptor_accessor\030" + "\002 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005false\022" + "\021\n\tmap_entry\030\007 \001(\010\022C\n\024uninterpreted_opti" "on\030\347\007 \003(\0132$.google.protobuf.Uninterprete" - "dOption\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCO" - "DE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346" - "\001\n\016MessageOptions\022&\n\027message_set_wire_fo" - "rmat\030\001 \001(\010:\005false\022.\n\037no_standard_descrip" - "tor_accessor\030\002 \001(\010:\005false\022\031\n\ndeprecated\030" - "\003 \001(\010:\005false\022\021\n\tmap_entry\030\007 \001(\010\022C\n\024unint" - "erpreted_option\030\347\007 \003(\0132$.google.protobuf" - ".UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\240\002\n\014Fiel" - "dOptions\022:\n\005ctype\030\001 \001(\0162#.google.protobu" - "f.FieldOptions.CType:\006STRING\022\016\n\006packed\030\002" - " \001(\010\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\ndeprecated\030" - "\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024uni" - "nterpreted_option\030\347\007 \003(\0132$.google.protob" - "uf.UninterpretedOption\"/\n\005CType\022\n\n\006STRIN" - "G\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002*\t\010\350\007\020\200\200\200" - "\200\002\"\215\001\n\013EnumOptions\022\023\n\013allow_alias\030\002 \001(\010\022" - "\031\n\ndeprecated\030\003 \001(\010:\005false\022C\n\024uninterpre" - "ted_option\030\347\007 \003(\0132$.google.protobuf.Unin" - "terpretedOption*\t\010\350\007\020\200\200\200\200\002\"}\n\020EnumValueO" - "ptions\022\031\n\ndeprecated\030\001 \001(\010:\005false\022C\n\024uni" - "nterpreted_option\030\347\007 \003(\0132$.google.protob" - "uf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016Ser" - "viceOptions\022\031\n\ndeprecated\030! \001(\010:\005false\022C" - "\n\024uninterpreted_option\030\347\007 \003(\0132$.google.p" - "rotobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"z" - "\n\rMethodOptions\022\031\n\ndeprecated\030! \001(\010:\005fal" - "se\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goog" - "le.protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200" - "\200\002\"\236\002\n\023UninterpretedOption\022;\n\004name\030\002 \003(\013" - "2-.google.protobuf.UninterpretedOption.N" - "amePart\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022pos" - "itive_int_value\030\004 \001(\004\022\032\n\022negative_int_va" - "lue\030\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014strin" - "g_value\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323" - "\n\010NamePart\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_exte" - "nsion\030\002 \002(\010\"\261\001\n\016SourceCodeInfo\022:\n\010locati" - "on\030\001 \003(\0132(.google.protobuf.SourceCodeInf" - "o.Location\032c\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001" - "\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003" - " \001(\t\022\031\n\021trailing_comments\030\004 \001(\tB)\n\023com.g" - "oogle.protobufB\020DescriptorProtosH\001", 4554); + "dOption*\t\010\350\007\020\200\200\200\200\002\"\240\002\n\014FieldOptions\022:\n\005c" + "type\030\001 \001(\0162#.google.protobuf.FieldOption" + "s.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\023\n\004lazy\030" + "\005 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005false\022" + "\023\n\004weak\030\n \001(\010:\005false\022C\n\024uninterpreted_op" + "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre" + "tedOption\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001" + "\022\020\n\014STRING_PIECE\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOp" + "tions\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\ndeprecated" + "\030\003 \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007" + " \003(\0132$.google.protobuf.UninterpretedOpti" + "on*\t\010\350\007\020\200\200\200\200\002\"}\n\020EnumValueOptions\022\031\n\ndep" + "recated\030\001 \001(\010:\005false\022C\n\024uninterpreted_op" + "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre" + "tedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031" + "\n\ndeprecated\030! \001(\010:\005false\022C\n\024uninterpret" + "ed_option\030\347\007 \003(\0132$.google.protobuf.Unint" + "erpretedOption*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptio" + "ns\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024uninter" + "preted_option\030\347\007 \003(\0132$.google.protobuf.U" + "ninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023Uninte" + "rpretedOption\022;\n\004name\030\002 \003(\0132-.google.pro" + "tobuf.UninterpretedOption.NamePart\022\030\n\020id" + "entifier_value\030\003 \001(\t\022\032\n\022positive_int_val" + "ue\030\004 \001(\004\022\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014" + "double_value\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014" + "\022\027\n\017aggregate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n" + "\tname_part\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\325" + "\001\n\016SourceCodeInfo\022:\n\010location\030\001 \003(\0132(.go" + "ogle.protobuf.SourceCodeInfo.Location\032\206\001" + "\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003" + "(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022\031\n\021trai" + "ling_comments\030\004 \001(\t\022!\n\031leading_detached_" + "comments\030\006 \003(\tB/\n\023com.google.protobufB\020D" + "escriptorProtosH\001\242\002\003GPB", 4623); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/descriptor.proto", &protobuf_RegisterTypes); FileDescriptorSet::default_instance_ = new FileDescriptorSet(); @@ -988,6 +1013,40 @@ void FileDescriptorSet::InternalSwap(FileDescriptorSet* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// FileDescriptorSet + +// repeated .google.protobuf.FileDescriptorProto file = 1; + int FileDescriptorSet::file_size() const { + return file_.size(); +} + void FileDescriptorSet::clear_file() { + file_.Clear(); +} + const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorSet.file) + return file_.Get(index); +} + ::google::protobuf::FileDescriptorProto* FileDescriptorSet::mutable_file(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorSet.file) + return file_.Mutable(index); +} + ::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorSet.file) + return file_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& +FileDescriptorSet::file() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file) + return file_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* +FileDescriptorSet::mutable_file() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorSet.file) + return &file_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -1750,6 +1809,489 @@ void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// FileDescriptorProto + +// optional string name = 1; + bool FileDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void FileDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} + void FileDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} + void FileDescriptorProto::clear_name() { + name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name(); +} + const ::std::string& FileDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.name) + return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.name) +} + void FileDescriptorProto::set_name(const char* value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.name) +} + void FileDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.name) +} + ::std::string* FileDescriptorProto::mutable_name() { + set_has_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.name) + return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FileDescriptorProto::release_name() { + clear_has_name(); + return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileDescriptorProto::set_allocated_name(::std::string* name) { + if (name != NULL) { + set_has_name(); + } else { + clear_has_name(); + } + name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.name) +} + +// optional string package = 2; + bool FileDescriptorProto::has_package() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void FileDescriptorProto::set_has_package() { + _has_bits_[0] |= 0x00000002u; +} + void FileDescriptorProto::clear_has_package() { + _has_bits_[0] &= ~0x00000002u; +} + void FileDescriptorProto::clear_package() { + package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_package(); +} + const ::std::string& FileDescriptorProto::package() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.package) + return package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileDescriptorProto::set_package(const ::std::string& value) { + set_has_package(); + package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.package) +} + void FileDescriptorProto::set_package(const char* value) { + set_has_package(); + package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.package) +} + void FileDescriptorProto::set_package(const char* value, size_t size) { + set_has_package(); + package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.package) +} + ::std::string* FileDescriptorProto::mutable_package() { + set_has_package(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.package) + return package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FileDescriptorProto::release_package() { + clear_has_package(); + return package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileDescriptorProto::set_allocated_package(::std::string* package) { + if (package != NULL) { + set_has_package(); + } else { + clear_has_package(); + } + package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), package); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.package) +} + +// repeated string dependency = 3; + int FileDescriptorProto::dependency_size() const { + return dependency_.size(); +} + void FileDescriptorProto::clear_dependency() { + dependency_.Clear(); +} + const ::std::string& FileDescriptorProto::dependency(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.dependency) + return dependency_.Get(index); +} + ::std::string* FileDescriptorProto::mutable_dependency(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.dependency) + return dependency_.Mutable(index); +} + void FileDescriptorProto::set_dependency(int index, const ::std::string& value) { + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency) + dependency_.Mutable(index)->assign(value); +} + void FileDescriptorProto::set_dependency(int index, const char* value) { + dependency_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.dependency) +} + void FileDescriptorProto::set_dependency(int index, const char* value, size_t size) { + dependency_.Mutable(index)->assign( + reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.dependency) +} + ::std::string* FileDescriptorProto::add_dependency() { + return dependency_.Add(); +} + void FileDescriptorProto::add_dependency(const ::std::string& value) { + dependency_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.dependency) +} + void FileDescriptorProto::add_dependency(const char* value) { + dependency_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.FileDescriptorProto.dependency) +} + void FileDescriptorProto::add_dependency(const char* value, size_t size) { + dependency_.Add()->assign(reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.FileDescriptorProto.dependency) +} + const ::google::protobuf::RepeatedPtrField< ::std::string>& +FileDescriptorProto::dependency() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.dependency) + return dependency_; +} + ::google::protobuf::RepeatedPtrField< ::std::string>* +FileDescriptorProto::mutable_dependency() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.dependency) + return &dependency_; +} + +// repeated int32 public_dependency = 10; + int FileDescriptorProto::public_dependency_size() const { + return public_dependency_.size(); +} + void FileDescriptorProto::clear_public_dependency() { + public_dependency_.Clear(); +} + ::google::protobuf::int32 FileDescriptorProto::public_dependency(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.public_dependency) + return public_dependency_.Get(index); +} + void FileDescriptorProto::set_public_dependency(int index, ::google::protobuf::int32 value) { + public_dependency_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.public_dependency) +} + void FileDescriptorProto::add_public_dependency(::google::protobuf::int32 value) { + public_dependency_.Add(value); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.public_dependency) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +FileDescriptorProto::public_dependency() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.public_dependency) + return public_dependency_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +FileDescriptorProto::mutable_public_dependency() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.public_dependency) + return &public_dependency_; +} + +// repeated int32 weak_dependency = 11; + int FileDescriptorProto::weak_dependency_size() const { + return weak_dependency_.size(); +} + void FileDescriptorProto::clear_weak_dependency() { + weak_dependency_.Clear(); +} + ::google::protobuf::int32 FileDescriptorProto::weak_dependency(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.weak_dependency) + return weak_dependency_.Get(index); +} + void FileDescriptorProto::set_weak_dependency(int index, ::google::protobuf::int32 value) { + weak_dependency_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.weak_dependency) +} + void FileDescriptorProto::add_weak_dependency(::google::protobuf::int32 value) { + weak_dependency_.Add(value); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.weak_dependency) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +FileDescriptorProto::weak_dependency() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.weak_dependency) + return weak_dependency_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +FileDescriptorProto::mutable_weak_dependency() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.weak_dependency) + return &weak_dependency_; +} + +// repeated .google.protobuf.DescriptorProto message_type = 4; + int FileDescriptorProto::message_type_size() const { + return message_type_.size(); +} + void FileDescriptorProto::clear_message_type() { + message_type_.Clear(); +} + const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.message_type) + return message_type_.Get(index); +} + ::google::protobuf::DescriptorProto* FileDescriptorProto::mutable_message_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.message_type) + return message_type_.Mutable(index); +} + ::google::protobuf::DescriptorProto* FileDescriptorProto::add_message_type() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.message_type) + return message_type_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& +FileDescriptorProto::message_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type) + return message_type_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* +FileDescriptorProto::mutable_message_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.message_type) + return &message_type_; +} + +// repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + int FileDescriptorProto::enum_type_size() const { + return enum_type_.size(); +} + void FileDescriptorProto::clear_enum_type() { + enum_type_.Clear(); +} + const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.enum_type) + return enum_type_.Get(index); +} + ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::mutable_enum_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.enum_type) + return enum_type_.Mutable(index); +} + ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::add_enum_type() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.enum_type) + return enum_type_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& +FileDescriptorProto::enum_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type) + return enum_type_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* +FileDescriptorProto::mutable_enum_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.enum_type) + return &enum_type_; +} + +// repeated .google.protobuf.ServiceDescriptorProto service = 6; + int FileDescriptorProto::service_size() const { + return service_.size(); +} + void FileDescriptorProto::clear_service() { + service_.Clear(); +} + const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.service) + return service_.Get(index); +} + ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::mutable_service(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.service) + return service_.Mutable(index); +} + ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::add_service() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.service) + return service_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >& +FileDescriptorProto::service() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service) + return service_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >* +FileDescriptorProto::mutable_service() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.service) + return &service_; +} + +// repeated .google.protobuf.FieldDescriptorProto extension = 7; + int FileDescriptorProto::extension_size() const { + return extension_.size(); +} + void FileDescriptorProto::clear_extension() { + extension_.Clear(); +} + const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.extension) + return extension_.Get(index); +} + ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::mutable_extension(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.extension) + return extension_.Mutable(index); +} + ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::add_extension() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.extension) + return extension_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& +FileDescriptorProto::extension() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension) + return extension_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* +FileDescriptorProto::mutable_extension() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.extension) + return &extension_; +} + +// optional .google.protobuf.FileOptions options = 8; + bool FileDescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000200u) != 0; +} + void FileDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000200u; +} + void FileDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000200u; +} + void FileDescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear(); + clear_has_options(); +} + const ::google::protobuf::FileOptions& FileDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.options) + return options_ != NULL ? *options_ : *default_instance_->options_; +} + ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) { + options_ = new ::google::protobuf::FileOptions; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.options) + return options_; +} + ::google::protobuf::FileOptions* FileDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::FileOptions* temp = options_; + options_ = NULL; + return temp; +} + void FileDescriptorProto::set_allocated_options(::google::protobuf::FileOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.options) +} + +// optional .google.protobuf.SourceCodeInfo source_code_info = 9; + bool FileDescriptorProto::has_source_code_info() const { + return (_has_bits_[0] & 0x00000400u) != 0; +} + void FileDescriptorProto::set_has_source_code_info() { + _has_bits_[0] |= 0x00000400u; +} + void FileDescriptorProto::clear_has_source_code_info() { + _has_bits_[0] &= ~0x00000400u; +} + void FileDescriptorProto::clear_source_code_info() { + if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear(); + clear_has_source_code_info(); +} + const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.source_code_info) + return source_code_info_ != NULL ? *source_code_info_ : *default_instance_->source_code_info_; +} + ::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() { + set_has_source_code_info(); + if (source_code_info_ == NULL) { + source_code_info_ = new ::google::protobuf::SourceCodeInfo; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.source_code_info) + return source_code_info_; +} + ::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() { + clear_has_source_code_info(); + ::google::protobuf::SourceCodeInfo* temp = source_code_info_; + source_code_info_ = NULL; + return temp; +} + void FileDescriptorProto::set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info) { + delete source_code_info_; + source_code_info_ = source_code_info; + if (source_code_info) { + set_has_source_code_info(); + } else { + clear_has_source_code_info(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.source_code_info) +} + +// optional string syntax = 12; + bool FileDescriptorProto::has_syntax() const { + return (_has_bits_[0] & 0x00000800u) != 0; +} + void FileDescriptorProto::set_has_syntax() { + _has_bits_[0] |= 0x00000800u; +} + void FileDescriptorProto::clear_has_syntax() { + _has_bits_[0] &= ~0x00000800u; +} + void FileDescriptorProto::clear_syntax() { + syntax_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_syntax(); +} + const ::std::string& FileDescriptorProto::syntax() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.syntax) + return syntax_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileDescriptorProto::set_syntax(const ::std::string& value) { + set_has_syntax(); + syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.syntax) +} + void FileDescriptorProto::set_syntax(const char* value) { + set_has_syntax(); + syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.syntax) +} + void FileDescriptorProto::set_syntax(const char* value, size_t size) { + set_has_syntax(); + syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.syntax) +} + ::std::string* FileDescriptorProto::mutable_syntax() { + set_has_syntax(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.syntax) + return syntax_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FileDescriptorProto::release_syntax() { + clear_has_syntax(); + return syntax_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileDescriptorProto::set_allocated_syntax(::std::string* syntax) { + if (syntax != NULL) { + set_has_syntax(); + } else { + clear_has_syntax(); + } + syntax_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), syntax); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.syntax) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -1818,19 +2360,17 @@ DescriptorProto_ExtensionRange* DescriptorProto_ExtensionRange::New(::google::pr } void DescriptorProto_ExtensionRange::Clear() { -#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \ - &reinterpret_cast<DescriptorProto_ExtensionRange*>(16)->f) - \ - reinterpret_cast<char*>(16)) +#define ZR_HELPER_(f) reinterpret_cast<char*>(\ + &reinterpret_cast<DescriptorProto_ExtensionRange*>(16)->f) -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) ZR_(start_, end_); -#undef OFFSET_OF_FIELD_ +#undef ZR_HELPER_ #undef ZR_ ::memset(_has_bits_, 0, sizeof(_has_bits_)); @@ -2573,6 +3113,338 @@ void DescriptorProto::InternalSwap(DescriptorProto* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// DescriptorProto_ExtensionRange + +// optional int32 start = 1; + bool DescriptorProto_ExtensionRange::has_start() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void DescriptorProto_ExtensionRange::set_has_start() { + _has_bits_[0] |= 0x00000001u; +} + void DescriptorProto_ExtensionRange::clear_has_start() { + _has_bits_[0] &= ~0x00000001u; +} + void DescriptorProto_ExtensionRange::clear_start() { + start_ = 0; + clear_has_start(); +} + ::google::protobuf::int32 DescriptorProto_ExtensionRange::start() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.start) + return start_; +} + void DescriptorProto_ExtensionRange::set_start(::google::protobuf::int32 value) { + set_has_start(); + start_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.start) +} + +// optional int32 end = 2; + bool DescriptorProto_ExtensionRange::has_end() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void DescriptorProto_ExtensionRange::set_has_end() { + _has_bits_[0] |= 0x00000002u; +} + void DescriptorProto_ExtensionRange::clear_has_end() { + _has_bits_[0] &= ~0x00000002u; +} + void DescriptorProto_ExtensionRange::clear_end() { + end_ = 0; + clear_has_end(); +} + ::google::protobuf::int32 DescriptorProto_ExtensionRange::end() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.end) + return end_; +} + void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 value) { + set_has_end(); + end_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.end) +} + +// ------------------------------------------------------------------- + +// DescriptorProto + +// optional string name = 1; + bool DescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void DescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} + void DescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} + void DescriptorProto::clear_name() { + name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name(); +} + const ::std::string& DescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.name) + return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void DescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.name) +} + void DescriptorProto::set_name(const char* value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.name) +} + void DescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.name) +} + ::std::string* DescriptorProto::mutable_name() { + set_has_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.name) + return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* DescriptorProto::release_name() { + clear_has_name(); + return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void DescriptorProto::set_allocated_name(::std::string* name) { + if (name != NULL) { + set_has_name(); + } else { + clear_has_name(); + } + name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.name) +} + +// repeated .google.protobuf.FieldDescriptorProto field = 2; + int DescriptorProto::field_size() const { + return field_.size(); +} + void DescriptorProto::clear_field() { + field_.Clear(); +} + const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.field) + return field_.Get(index); +} + ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_field(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.field) + return field_.Mutable(index); +} + ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_field() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.field) + return field_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& +DescriptorProto::field() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field) + return field_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* +DescriptorProto::mutable_field() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.field) + return &field_; +} + +// repeated .google.protobuf.FieldDescriptorProto extension = 6; + int DescriptorProto::extension_size() const { + return extension_.size(); +} + void DescriptorProto::clear_extension() { + extension_.Clear(); +} + const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension) + return extension_.Get(index); +} + ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_extension(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension) + return extension_.Mutable(index); +} + ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_extension() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension) + return extension_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& +DescriptorProto::extension() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension) + return extension_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* +DescriptorProto::mutable_extension() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension) + return &extension_; +} + +// repeated .google.protobuf.DescriptorProto nested_type = 3; + int DescriptorProto::nested_type_size() const { + return nested_type_.size(); +} + void DescriptorProto::clear_nested_type() { + nested_type_.Clear(); +} + const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.nested_type) + return nested_type_.Get(index); +} + ::google::protobuf::DescriptorProto* DescriptorProto::mutable_nested_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.nested_type) + return nested_type_.Mutable(index); +} + ::google::protobuf::DescriptorProto* DescriptorProto::add_nested_type() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.nested_type) + return nested_type_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& +DescriptorProto::nested_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type) + return nested_type_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* +DescriptorProto::mutable_nested_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.nested_type) + return &nested_type_; +} + +// repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + int DescriptorProto::enum_type_size() const { + return enum_type_.size(); +} + void DescriptorProto::clear_enum_type() { + enum_type_.Clear(); +} + const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.enum_type) + return enum_type_.Get(index); +} + ::google::protobuf::EnumDescriptorProto* DescriptorProto::mutable_enum_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.enum_type) + return enum_type_.Mutable(index); +} + ::google::protobuf::EnumDescriptorProto* DescriptorProto::add_enum_type() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.enum_type) + return enum_type_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& +DescriptorProto::enum_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type) + return enum_type_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* +DescriptorProto::mutable_enum_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.enum_type) + return &enum_type_; +} + +// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + int DescriptorProto::extension_range_size() const { + return extension_range_.size(); +} + void DescriptorProto::clear_extension_range() { + extension_range_.Clear(); +} + const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension_range) + return extension_range_.Get(index); +} + ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::mutable_extension_range(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension_range) + return extension_range_.Mutable(index); +} + ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::add_extension_range() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension_range) + return extension_range_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >& +DescriptorProto::extension_range() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension_range) + return extension_range_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >* +DescriptorProto::mutable_extension_range() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension_range) + return &extension_range_; +} + +// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + int DescriptorProto::oneof_decl_size() const { + return oneof_decl_.size(); +} + void DescriptorProto::clear_oneof_decl() { + oneof_decl_.Clear(); +} + const ::google::protobuf::OneofDescriptorProto& DescriptorProto::oneof_decl(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.oneof_decl) + return oneof_decl_.Get(index); +} + ::google::protobuf::OneofDescriptorProto* DescriptorProto::mutable_oneof_decl(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.oneof_decl) + return oneof_decl_.Mutable(index); +} + ::google::protobuf::OneofDescriptorProto* DescriptorProto::add_oneof_decl() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.oneof_decl) + return oneof_decl_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >& +DescriptorProto::oneof_decl() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl) + return oneof_decl_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >* +DescriptorProto::mutable_oneof_decl() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.oneof_decl) + return &oneof_decl_; +} + +// optional .google.protobuf.MessageOptions options = 7; + bool DescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000080u) != 0; +} + void DescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000080u; +} + void DescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000080u; +} + void DescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear(); + clear_has_options(); +} + const ::google::protobuf::MessageOptions& DescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.options) + return options_ != NULL ? *options_ : *default_instance_->options_; +} + ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) { + options_ = new ::google::protobuf::MessageOptions; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.options) + return options_; +} + ::google::protobuf::MessageOptions* DescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::MessageOptions* temp = options_; + options_ = NULL; + return temp; +} + void DescriptorProto::set_allocated_options(::google::protobuf::MessageOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.options) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -3287,6 +4159,363 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// FieldDescriptorProto + +// optional string name = 1; + bool FieldDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void FieldDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} + void FieldDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} + void FieldDescriptorProto::clear_name() { + name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name(); +} + const ::std::string& FieldDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.name) + return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FieldDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.name) +} + void FieldDescriptorProto::set_name(const char* value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.name) +} + void FieldDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.name) +} + ::std::string* FieldDescriptorProto::mutable_name() { + set_has_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.name) + return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FieldDescriptorProto::release_name() { + clear_has_name(); + return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FieldDescriptorProto::set_allocated_name(::std::string* name) { + if (name != NULL) { + set_has_name(); + } else { + clear_has_name(); + } + name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.name) +} + +// optional int32 number = 3; + bool FieldDescriptorProto::has_number() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void FieldDescriptorProto::set_has_number() { + _has_bits_[0] |= 0x00000002u; +} + void FieldDescriptorProto::clear_has_number() { + _has_bits_[0] &= ~0x00000002u; +} + void FieldDescriptorProto::clear_number() { + number_ = 0; + clear_has_number(); +} + ::google::protobuf::int32 FieldDescriptorProto::number() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.number) + return number_; +} + void FieldDescriptorProto::set_number(::google::protobuf::int32 value) { + set_has_number(); + number_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.number) +} + +// optional .google.protobuf.FieldDescriptorProto.Label label = 4; + bool FieldDescriptorProto::has_label() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void FieldDescriptorProto::set_has_label() { + _has_bits_[0] |= 0x00000004u; +} + void FieldDescriptorProto::clear_has_label() { + _has_bits_[0] &= ~0x00000004u; +} + void FieldDescriptorProto::clear_label() { + label_ = 1; + clear_has_label(); +} + ::google::protobuf::FieldDescriptorProto_Label FieldDescriptorProto::label() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.label) + return static_cast< ::google::protobuf::FieldDescriptorProto_Label >(label_); +} + void FieldDescriptorProto::set_label(::google::protobuf::FieldDescriptorProto_Label value) { + assert(::google::protobuf::FieldDescriptorProto_Label_IsValid(value)); + set_has_label(); + label_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.label) +} + +// optional .google.protobuf.FieldDescriptorProto.Type type = 5; + bool FieldDescriptorProto::has_type() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} + void FieldDescriptorProto::set_has_type() { + _has_bits_[0] |= 0x00000008u; +} + void FieldDescriptorProto::clear_has_type() { + _has_bits_[0] &= ~0x00000008u; +} + void FieldDescriptorProto::clear_type() { + type_ = 1; + clear_has_type(); +} + ::google::protobuf::FieldDescriptorProto_Type FieldDescriptorProto::type() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type) + return static_cast< ::google::protobuf::FieldDescriptorProto_Type >(type_); +} + void FieldDescriptorProto::set_type(::google::protobuf::FieldDescriptorProto_Type value) { + assert(::google::protobuf::FieldDescriptorProto_Type_IsValid(value)); + set_has_type(); + type_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type) +} + +// optional string type_name = 6; + bool FieldDescriptorProto::has_type_name() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} + void FieldDescriptorProto::set_has_type_name() { + _has_bits_[0] |= 0x00000010u; +} + void FieldDescriptorProto::clear_has_type_name() { + _has_bits_[0] &= ~0x00000010u; +} + void FieldDescriptorProto::clear_type_name() { + type_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_type_name(); +} + const ::std::string& FieldDescriptorProto::type_name() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type_name) + return type_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FieldDescriptorProto::set_type_name(const ::std::string& value) { + set_has_type_name(); + type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type_name) +} + void FieldDescriptorProto::set_type_name(const char* value) { + set_has_type_name(); + type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.type_name) +} + void FieldDescriptorProto::set_type_name(const char* value, size_t size) { + set_has_type_name(); + type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.type_name) +} + ::std::string* FieldDescriptorProto::mutable_type_name() { + set_has_type_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.type_name) + return type_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FieldDescriptorProto::release_type_name() { + clear_has_type_name(); + return type_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FieldDescriptorProto::set_allocated_type_name(::std::string* type_name) { + if (type_name != NULL) { + set_has_type_name(); + } else { + clear_has_type_name(); + } + type_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.type_name) +} + +// optional string extendee = 2; + bool FieldDescriptorProto::has_extendee() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} + void FieldDescriptorProto::set_has_extendee() { + _has_bits_[0] |= 0x00000020u; +} + void FieldDescriptorProto::clear_has_extendee() { + _has_bits_[0] &= ~0x00000020u; +} + void FieldDescriptorProto::clear_extendee() { + extendee_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_extendee(); +} + const ::std::string& FieldDescriptorProto::extendee() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.extendee) + return extendee_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FieldDescriptorProto::set_extendee(const ::std::string& value) { + set_has_extendee(); + extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.extendee) +} + void FieldDescriptorProto::set_extendee(const char* value) { + set_has_extendee(); + extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.extendee) +} + void FieldDescriptorProto::set_extendee(const char* value, size_t size) { + set_has_extendee(); + extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.extendee) +} + ::std::string* FieldDescriptorProto::mutable_extendee() { + set_has_extendee(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.extendee) + return extendee_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FieldDescriptorProto::release_extendee() { + clear_has_extendee(); + return extendee_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FieldDescriptorProto::set_allocated_extendee(::std::string* extendee) { + if (extendee != NULL) { + set_has_extendee(); + } else { + clear_has_extendee(); + } + extendee_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), extendee); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.extendee) +} + +// optional string default_value = 7; + bool FieldDescriptorProto::has_default_value() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} + void FieldDescriptorProto::set_has_default_value() { + _has_bits_[0] |= 0x00000040u; +} + void FieldDescriptorProto::clear_has_default_value() { + _has_bits_[0] &= ~0x00000040u; +} + void FieldDescriptorProto::clear_default_value() { + default_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_default_value(); +} + const ::std::string& FieldDescriptorProto::default_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.default_value) + return default_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FieldDescriptorProto::set_default_value(const ::std::string& value) { + set_has_default_value(); + default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.default_value) +} + void FieldDescriptorProto::set_default_value(const char* value) { + set_has_default_value(); + default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.default_value) +} + void FieldDescriptorProto::set_default_value(const char* value, size_t size) { + set_has_default_value(); + default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.default_value) +} + ::std::string* FieldDescriptorProto::mutable_default_value() { + set_has_default_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.default_value) + return default_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FieldDescriptorProto::release_default_value() { + clear_has_default_value(); + return default_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FieldDescriptorProto::set_allocated_default_value(::std::string* default_value) { + if (default_value != NULL) { + set_has_default_value(); + } else { + clear_has_default_value(); + } + default_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), default_value); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.default_value) +} + +// optional int32 oneof_index = 9; + bool FieldDescriptorProto::has_oneof_index() const { + return (_has_bits_[0] & 0x00000080u) != 0; +} + void FieldDescriptorProto::set_has_oneof_index() { + _has_bits_[0] |= 0x00000080u; +} + void FieldDescriptorProto::clear_has_oneof_index() { + _has_bits_[0] &= ~0x00000080u; +} + void FieldDescriptorProto::clear_oneof_index() { + oneof_index_ = 0; + clear_has_oneof_index(); +} + ::google::protobuf::int32 FieldDescriptorProto::oneof_index() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.oneof_index) + return oneof_index_; +} + void FieldDescriptorProto::set_oneof_index(::google::protobuf::int32 value) { + set_has_oneof_index(); + oneof_index_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.oneof_index) +} + +// optional .google.protobuf.FieldOptions options = 8; + bool FieldDescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000100u) != 0; +} + void FieldDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000100u; +} + void FieldDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000100u; +} + void FieldDescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear(); + clear_has_options(); +} + const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.options) + return options_ != NULL ? *options_ : *default_instance_->options_; +} + ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) { + options_ = new ::google::protobuf::FieldOptions; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.options) + return options_; +} + ::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::FieldOptions* temp = options_; + options_ = NULL; + return temp; +} + void FieldDescriptorProto::set_allocated_options(::google::protobuf::FieldOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.options) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -3536,6 +4765,63 @@ void OneofDescriptorProto::InternalSwap(OneofDescriptorProto* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// OneofDescriptorProto + +// optional string name = 1; + bool OneofDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void OneofDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} + void OneofDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} + void OneofDescriptorProto::clear_name() { + name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name(); +} + const ::std::string& OneofDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.name) + return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void OneofDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.OneofDescriptorProto.name) +} + void OneofDescriptorProto::set_name(const char* value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.OneofDescriptorProto.name) +} + void OneofDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.OneofDescriptorProto.name) +} + ::std::string* OneofDescriptorProto::mutable_name() { + set_has_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.OneofDescriptorProto.name) + return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* OneofDescriptorProto::release_name() { + clear_has_name(); + return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void OneofDescriptorProto::set_allocated_name(::std::string* name) { + if (name != NULL) { + set_has_name(); + } else { + clear_has_name(); + } + name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.name) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -3876,6 +5162,136 @@ void EnumDescriptorProto::InternalSwap(EnumDescriptorProto* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// EnumDescriptorProto + +// optional string name = 1; + bool EnumDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void EnumDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} + void EnumDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} + void EnumDescriptorProto::clear_name() { + name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name(); +} + const ::std::string& EnumDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.name) + return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void EnumDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.name) +} + void EnumDescriptorProto::set_name(const char* value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.name) +} + void EnumDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.name) +} + ::std::string* EnumDescriptorProto::mutable_name() { + set_has_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.name) + return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* EnumDescriptorProto::release_name() { + clear_has_name(); + return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void EnumDescriptorProto::set_allocated_name(::std::string* name) { + if (name != NULL) { + set_has_name(); + } else { + clear_has_name(); + } + name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.name) +} + +// repeated .google.protobuf.EnumValueDescriptorProto value = 2; + int EnumDescriptorProto::value_size() const { + return value_.size(); +} + void EnumDescriptorProto::clear_value() { + value_.Clear(); +} + const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.value) + return value_.Get(index); +} + ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::mutable_value(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.value) + return value_.Mutable(index); +} + ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::add_value() { + // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.value) + return value_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >& +EnumDescriptorProto::value() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value) + return value_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >* +EnumDescriptorProto::mutable_value() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.value) + return &value_; +} + +// optional .google.protobuf.EnumOptions options = 3; + bool EnumDescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void EnumDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000004u; +} + void EnumDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000004u; +} + void EnumDescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear(); + clear_has_options(); +} + const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.options) + return options_ != NULL ? *options_ : *default_instance_->options_; +} + ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) { + options_ = new ::google::protobuf::EnumOptions; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.options) + return options_; +} + ::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::EnumOptions* temp = options_; + options_ = NULL; + return temp; +} + void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.options) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -4215,6 +5631,130 @@ void EnumValueDescriptorProto::InternalSwap(EnumValueDescriptorProto* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// EnumValueDescriptorProto + +// optional string name = 1; + bool EnumValueDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void EnumValueDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} + void EnumValueDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} + void EnumValueDescriptorProto::clear_name() { + name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name(); +} + const ::std::string& EnumValueDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.name) + return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void EnumValueDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.name) +} + void EnumValueDescriptorProto::set_name(const char* value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValueDescriptorProto.name) +} + void EnumValueDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValueDescriptorProto.name) +} + ::std::string* EnumValueDescriptorProto::mutable_name() { + set_has_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.name) + return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* EnumValueDescriptorProto::release_name() { + clear_has_name(); + return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void EnumValueDescriptorProto::set_allocated_name(::std::string* name) { + if (name != NULL) { + set_has_name(); + } else { + clear_has_name(); + } + name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.name) +} + +// optional int32 number = 2; + bool EnumValueDescriptorProto::has_number() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void EnumValueDescriptorProto::set_has_number() { + _has_bits_[0] |= 0x00000002u; +} + void EnumValueDescriptorProto::clear_has_number() { + _has_bits_[0] &= ~0x00000002u; +} + void EnumValueDescriptorProto::clear_number() { + number_ = 0; + clear_has_number(); +} + ::google::protobuf::int32 EnumValueDescriptorProto::number() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.number) + return number_; +} + void EnumValueDescriptorProto::set_number(::google::protobuf::int32 value) { + set_has_number(); + number_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.number) +} + +// optional .google.protobuf.EnumValueOptions options = 3; + bool EnumValueDescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void EnumValueDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000004u; +} + void EnumValueDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000004u; +} + void EnumValueDescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear(); + clear_has_options(); +} + const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.options) + return options_ != NULL ? *options_ : *default_instance_->options_; +} + ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) { + options_ = new ::google::protobuf::EnumValueOptions; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.options) + return options_; +} + ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::EnumValueOptions* temp = options_; + options_ = NULL; + return temp; +} + void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::EnumValueOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.options) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -4555,6 +6095,136 @@ void ServiceDescriptorProto::InternalSwap(ServiceDescriptorProto* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// ServiceDescriptorProto + +// optional string name = 1; + bool ServiceDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void ServiceDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} + void ServiceDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} + void ServiceDescriptorProto::clear_name() { + name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name(); +} + const ::std::string& ServiceDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.name) + return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void ServiceDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.ServiceDescriptorProto.name) +} + void ServiceDescriptorProto::set_name(const char* value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.ServiceDescriptorProto.name) +} + void ServiceDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.ServiceDescriptorProto.name) +} + ::std::string* ServiceDescriptorProto::mutable_name() { + set_has_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.name) + return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* ServiceDescriptorProto::release_name() { + clear_has_name(); + return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void ServiceDescriptorProto::set_allocated_name(::std::string* name) { + if (name != NULL) { + set_has_name(); + } else { + clear_has_name(); + } + name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.name) +} + +// repeated .google.protobuf.MethodDescriptorProto method = 2; + int ServiceDescriptorProto::method_size() const { + return method_.size(); +} + void ServiceDescriptorProto::clear_method() { + method_.Clear(); +} + const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.method) + return method_.Get(index); +} + ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::mutable_method(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.method) + return method_.Mutable(index); +} + ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::add_method() { + // @@protoc_insertion_point(field_add:google.protobuf.ServiceDescriptorProto.method) + return method_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >& +ServiceDescriptorProto::method() const { + // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method) + return method_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >* +ServiceDescriptorProto::mutable_method() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceDescriptorProto.method) + return &method_; +} + +// optional .google.protobuf.ServiceOptions options = 3; + bool ServiceDescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void ServiceDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000004u; +} + void ServiceDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000004u; +} + void ServiceDescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear(); + clear_has_options(); +} + const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.options) + return options_ != NULL ? *options_ : *default_instance_->options_; +} + ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) { + options_ = new ::google::protobuf::ServiceOptions; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.options) + return options_; +} + ::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::ServiceOptions* temp = options_; + options_ = NULL; + return temp; +} + void ServiceDescriptorProto::set_allocated_options(::google::protobuf::ServiceOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.options) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -4637,15 +6307,13 @@ MethodDescriptorProto* MethodDescriptorProto::New(::google::protobuf::Arena* are } void MethodDescriptorProto::Clear() { -#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \ - &reinterpret_cast<MethodDescriptorProto*>(16)->f) - \ - reinterpret_cast<char*>(16)) +#define ZR_HELPER_(f) reinterpret_cast<char*>(\ + &reinterpret_cast<MethodDescriptorProto*>(16)->f) -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) if (_has_bits_[0 / 32] & 63) { ZR_(client_streaming_, server_streaming_); @@ -4663,7 +6331,7 @@ void MethodDescriptorProto::Clear() { } } -#undef OFFSET_OF_FIELD_ +#undef ZR_HELPER_ #undef ZR_ ::memset(_has_bits_, 0, sizeof(_has_bits_)); @@ -5054,6 +6722,260 @@ void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// MethodDescriptorProto + +// optional string name = 1; + bool MethodDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void MethodDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} + void MethodDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} + void MethodDescriptorProto::clear_name() { + name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name(); +} + const ::std::string& MethodDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.name) + return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void MethodDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.name) +} + void MethodDescriptorProto::set_name(const char* value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.name) +} + void MethodDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.name) +} + ::std::string* MethodDescriptorProto::mutable_name() { + set_has_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.name) + return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* MethodDescriptorProto::release_name() { + clear_has_name(); + return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void MethodDescriptorProto::set_allocated_name(::std::string* name) { + if (name != NULL) { + set_has_name(); + } else { + clear_has_name(); + } + name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.name) +} + +// optional string input_type = 2; + bool MethodDescriptorProto::has_input_type() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void MethodDescriptorProto::set_has_input_type() { + _has_bits_[0] |= 0x00000002u; +} + void MethodDescriptorProto::clear_has_input_type() { + _has_bits_[0] &= ~0x00000002u; +} + void MethodDescriptorProto::clear_input_type() { + input_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_input_type(); +} + const ::std::string& MethodDescriptorProto::input_type() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.input_type) + return input_type_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void MethodDescriptorProto::set_input_type(const ::std::string& value) { + set_has_input_type(); + input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.input_type) +} + void MethodDescriptorProto::set_input_type(const char* value) { + set_has_input_type(); + input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.input_type) +} + void MethodDescriptorProto::set_input_type(const char* value, size_t size) { + set_has_input_type(); + input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.input_type) +} + ::std::string* MethodDescriptorProto::mutable_input_type() { + set_has_input_type(); + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.input_type) + return input_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* MethodDescriptorProto::release_input_type() { + clear_has_input_type(); + return input_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void MethodDescriptorProto::set_allocated_input_type(::std::string* input_type) { + if (input_type != NULL) { + set_has_input_type(); + } else { + clear_has_input_type(); + } + input_type_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), input_type); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.input_type) +} + +// optional string output_type = 3; + bool MethodDescriptorProto::has_output_type() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void MethodDescriptorProto::set_has_output_type() { + _has_bits_[0] |= 0x00000004u; +} + void MethodDescriptorProto::clear_has_output_type() { + _has_bits_[0] &= ~0x00000004u; +} + void MethodDescriptorProto::clear_output_type() { + output_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_output_type(); +} + const ::std::string& MethodDescriptorProto::output_type() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.output_type) + return output_type_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void MethodDescriptorProto::set_output_type(const ::std::string& value) { + set_has_output_type(); + output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.output_type) +} + void MethodDescriptorProto::set_output_type(const char* value) { + set_has_output_type(); + output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.output_type) +} + void MethodDescriptorProto::set_output_type(const char* value, size_t size) { + set_has_output_type(); + output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.output_type) +} + ::std::string* MethodDescriptorProto::mutable_output_type() { + set_has_output_type(); + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.output_type) + return output_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* MethodDescriptorProto::release_output_type() { + clear_has_output_type(); + return output_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void MethodDescriptorProto::set_allocated_output_type(::std::string* output_type) { + if (output_type != NULL) { + set_has_output_type(); + } else { + clear_has_output_type(); + } + output_type_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), output_type); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.output_type) +} + +// optional .google.protobuf.MethodOptions options = 4; + bool MethodDescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} + void MethodDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000008u; +} + void MethodDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000008u; +} + void MethodDescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear(); + clear_has_options(); +} + const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.options) + return options_ != NULL ? *options_ : *default_instance_->options_; +} + ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) { + options_ = new ::google::protobuf::MethodOptions; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.options) + return options_; +} + ::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::MethodOptions* temp = options_; + options_ = NULL; + return temp; +} + void MethodDescriptorProto::set_allocated_options(::google::protobuf::MethodOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.options) +} + +// optional bool client_streaming = 5 [default = false]; + bool MethodDescriptorProto::has_client_streaming() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} + void MethodDescriptorProto::set_has_client_streaming() { + _has_bits_[0] |= 0x00000010u; +} + void MethodDescriptorProto::clear_has_client_streaming() { + _has_bits_[0] &= ~0x00000010u; +} + void MethodDescriptorProto::clear_client_streaming() { + client_streaming_ = false; + clear_has_client_streaming(); +} + bool MethodDescriptorProto::client_streaming() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.client_streaming) + return client_streaming_; +} + void MethodDescriptorProto::set_client_streaming(bool value) { + set_has_client_streaming(); + client_streaming_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.client_streaming) +} + +// optional bool server_streaming = 6 [default = false]; + bool MethodDescriptorProto::has_server_streaming() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} + void MethodDescriptorProto::set_has_server_streaming() { + _has_bits_[0] |= 0x00000020u; +} + void MethodDescriptorProto::clear_has_server_streaming() { + _has_bits_[0] &= ~0x00000020u; +} + void MethodDescriptorProto::clear_server_streaming() { + server_streaming_ = false; + clear_has_server_streaming(); +} + bool MethodDescriptorProto::server_streaming() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.server_streaming) + return server_streaming_; +} + void MethodDescriptorProto::set_server_streaming(bool value) { + set_has_server_streaming(); + server_streaming_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.server_streaming) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -5093,6 +7015,7 @@ const int FileOptions::kJavaGenericServicesFieldNumber; const int FileOptions::kPyGenericServicesFieldNumber; const int FileOptions::kDeprecatedFieldNumber; const int FileOptions::kCcEnableArenasFieldNumber; +const int FileOptions::kObjcClassPrefixFieldNumber; const int FileOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER @@ -5128,6 +7051,7 @@ void FileOptions::SharedCtor() { py_generic_services_ = false; deprecated_ = false; cc_enable_arenas_ = false; + objc_class_prefix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -5140,6 +7064,7 @@ void FileOptions::SharedDtor() { java_package_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); java_outer_classname_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); go_package_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + objc_class_prefix_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); if (this != default_instance_) { } } @@ -5171,15 +7096,13 @@ FileOptions* FileOptions::New(::google::protobuf::Arena* arena) const { void FileOptions::Clear() { _extensions_.Clear(); -#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \ - &reinterpret_cast<FileOptions*>(16)->f) - \ - reinterpret_cast<char*>(16)) +#define ZR_HELPER_(f) reinterpret_cast<char*>(\ + &reinterpret_cast<FileOptions*>(16)->f) -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) if (_has_bits_[0 / 32] & 255) { ZR_(java_multiple_files_, cc_generic_services_); @@ -5194,9 +7117,14 @@ void FileOptions::Clear() { go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } } - ZR_(java_generic_services_, cc_enable_arenas_); + if (_has_bits_[8 / 32] & 7936) { + ZR_(java_generic_services_, cc_enable_arenas_); + if (has_objc_class_prefix()) { + objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + } -#undef OFFSET_OF_FIELD_ +#undef ZR_HELPER_ #undef ZR_ uninterpreted_option_.Clear(); @@ -5402,6 +7330,23 @@ bool FileOptions::MergePartialFromCodedStream( } else { goto handle_unusual; } + if (input->ExpectTag(290)) goto parse_objc_class_prefix; + break; + } + + // optional string objc_class_prefix = 36; + case 36: { + if (tag == 290) { + parse_objc_class_prefix: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_objc_class_prefix())); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->objc_class_prefix().data(), this->objc_class_prefix().length(), + ::google::protobuf::internal::WireFormat::PARSE, + "google.protobuf.FileOptions.objc_class_prefix"); + } else { + goto handle_unusual; + } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; break; } @@ -5526,6 +7471,16 @@ void FileOptions::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormatLite::WriteBool(31, this->cc_enable_arenas(), output); } + // optional string objc_class_prefix = 36; + if (has_objc_class_prefix()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->objc_class_prefix().data(), this->objc_class_prefix().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.objc_class_prefix"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 36, this->objc_class_prefix(), output); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( @@ -5625,6 +7580,17 @@ void FileOptions::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(31, this->cc_enable_arenas(), target); } + // optional string objc_class_prefix = 36; + if (has_objc_class_prefix()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->objc_class_prefix().data(), this->objc_class_prefix().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.objc_class_prefix"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 36, this->objc_class_prefix(), target); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) { target = ::google::protobuf::internal::WireFormatLite:: @@ -5696,7 +7662,7 @@ int FileOptions::ByteSize() const { } } - if (_has_bits_[8 / 32] & 3840) { + if (_has_bits_[8 / 32] & 7936) { // optional bool java_generic_services = 17 [default = false]; if (has_java_generic_services()) { total_size += 2 + 1; @@ -5717,6 +7683,13 @@ int FileOptions::ByteSize() const { total_size += 2 + 1; } + // optional string objc_class_prefix = 36; + if (has_objc_class_prefix()) { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->objc_class_prefix()); + } + } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); @@ -5796,6 +7769,10 @@ void FileOptions::MergeFrom(const FileOptions& from) { if (from.has_cc_enable_arenas()) { set_cc_enable_arenas(from.cc_enable_arenas()); } + if (from.has_objc_class_prefix()) { + set_has_objc_class_prefix(); + objc_class_prefix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.objc_class_prefix_); + } } _extensions_.MergeFrom(from._extensions_); if (from._internal_metadata_.have_unknown_fields()) { @@ -5839,6 +7816,7 @@ void FileOptions::InternalSwap(FileOptions* other) { std::swap(py_generic_services_, other->py_generic_services_); std::swap(deprecated_, other->deprecated_); std::swap(cc_enable_arenas_, other->cc_enable_arenas_); + objc_class_prefix_.Swap(&other->objc_class_prefix_); uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _internal_metadata_.Swap(&other->_internal_metadata_); @@ -5854,6 +7832,469 @@ void FileOptions::InternalSwap(FileOptions* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// FileOptions + +// optional string java_package = 1; + bool FileOptions::has_java_package() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void FileOptions::set_has_java_package() { + _has_bits_[0] |= 0x00000001u; +} + void FileOptions::clear_has_java_package() { + _has_bits_[0] &= ~0x00000001u; +} + void FileOptions::clear_java_package() { + java_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_java_package(); +} + const ::std::string& FileOptions::java_package() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_package) + return java_package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_java_package(const ::std::string& value) { + set_has_java_package(); + java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_package) +} + void FileOptions::set_java_package(const char* value) { + set_has_java_package(); + java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_package) +} + void FileOptions::set_java_package(const char* value, size_t size) { + set_has_java_package(); + java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_package) +} + ::std::string* FileOptions::mutable_java_package() { + set_has_java_package(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_package) + return java_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FileOptions::release_java_package() { + clear_has_java_package(); + return java_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_allocated_java_package(::std::string* java_package) { + if (java_package != NULL) { + set_has_java_package(); + } else { + clear_has_java_package(); + } + java_package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_package); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_package) +} + +// optional string java_outer_classname = 8; + bool FileOptions::has_java_outer_classname() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void FileOptions::set_has_java_outer_classname() { + _has_bits_[0] |= 0x00000002u; +} + void FileOptions::clear_has_java_outer_classname() { + _has_bits_[0] &= ~0x00000002u; +} + void FileOptions::clear_java_outer_classname() { + java_outer_classname_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_java_outer_classname(); +} + const ::std::string& FileOptions::java_outer_classname() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_outer_classname) + return java_outer_classname_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_java_outer_classname(const ::std::string& value) { + set_has_java_outer_classname(); + java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_outer_classname) +} + void FileOptions::set_java_outer_classname(const char* value) { + set_has_java_outer_classname(); + java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_outer_classname) +} + void FileOptions::set_java_outer_classname(const char* value, size_t size) { + set_has_java_outer_classname(); + java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_outer_classname) +} + ::std::string* FileOptions::mutable_java_outer_classname() { + set_has_java_outer_classname(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_outer_classname) + return java_outer_classname_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FileOptions::release_java_outer_classname() { + clear_has_java_outer_classname(); + return java_outer_classname_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_allocated_java_outer_classname(::std::string* java_outer_classname) { + if (java_outer_classname != NULL) { + set_has_java_outer_classname(); + } else { + clear_has_java_outer_classname(); + } + java_outer_classname_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_outer_classname); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_outer_classname) +} + +// optional bool java_multiple_files = 10 [default = false]; + bool FileOptions::has_java_multiple_files() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void FileOptions::set_has_java_multiple_files() { + _has_bits_[0] |= 0x00000004u; +} + void FileOptions::clear_has_java_multiple_files() { + _has_bits_[0] &= ~0x00000004u; +} + void FileOptions::clear_java_multiple_files() { + java_multiple_files_ = false; + clear_has_java_multiple_files(); +} + bool FileOptions::java_multiple_files() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_multiple_files) + return java_multiple_files_; +} + void FileOptions::set_java_multiple_files(bool value) { + set_has_java_multiple_files(); + java_multiple_files_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_multiple_files) +} + +// optional bool java_generate_equals_and_hash = 20 [default = false]; + bool FileOptions::has_java_generate_equals_and_hash() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} + void FileOptions::set_has_java_generate_equals_and_hash() { + _has_bits_[0] |= 0x00000008u; +} + void FileOptions::clear_has_java_generate_equals_and_hash() { + _has_bits_[0] &= ~0x00000008u; +} + void FileOptions::clear_java_generate_equals_and_hash() { + java_generate_equals_and_hash_ = false; + clear_has_java_generate_equals_and_hash(); +} + bool FileOptions::java_generate_equals_and_hash() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generate_equals_and_hash) + return java_generate_equals_and_hash_; +} + void FileOptions::set_java_generate_equals_and_hash(bool value) { + set_has_java_generate_equals_and_hash(); + java_generate_equals_and_hash_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generate_equals_and_hash) +} + +// optional bool java_string_check_utf8 = 27 [default = false]; + bool FileOptions::has_java_string_check_utf8() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} + void FileOptions::set_has_java_string_check_utf8() { + _has_bits_[0] |= 0x00000010u; +} + void FileOptions::clear_has_java_string_check_utf8() { + _has_bits_[0] &= ~0x00000010u; +} + void FileOptions::clear_java_string_check_utf8() { + java_string_check_utf8_ = false; + clear_has_java_string_check_utf8(); +} + bool FileOptions::java_string_check_utf8() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_string_check_utf8) + return java_string_check_utf8_; +} + void FileOptions::set_java_string_check_utf8(bool value) { + set_has_java_string_check_utf8(); + java_string_check_utf8_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_string_check_utf8) +} + +// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; + bool FileOptions::has_optimize_for() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} + void FileOptions::set_has_optimize_for() { + _has_bits_[0] |= 0x00000020u; +} + void FileOptions::clear_has_optimize_for() { + _has_bits_[0] &= ~0x00000020u; +} + void FileOptions::clear_optimize_for() { + optimize_for_ = 1; + clear_has_optimize_for(); +} + ::google::protobuf::FileOptions_OptimizeMode FileOptions::optimize_for() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.optimize_for) + return static_cast< ::google::protobuf::FileOptions_OptimizeMode >(optimize_for_); +} + void FileOptions::set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value) { + assert(::google::protobuf::FileOptions_OptimizeMode_IsValid(value)); + set_has_optimize_for(); + optimize_for_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.optimize_for) +} + +// optional string go_package = 11; + bool FileOptions::has_go_package() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} + void FileOptions::set_has_go_package() { + _has_bits_[0] |= 0x00000040u; +} + void FileOptions::clear_has_go_package() { + _has_bits_[0] &= ~0x00000040u; +} + void FileOptions::clear_go_package() { + go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_go_package(); +} + const ::std::string& FileOptions::go_package() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.go_package) + return go_package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_go_package(const ::std::string& value) { + set_has_go_package(); + go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.go_package) +} + void FileOptions::set_go_package(const char* value) { + set_has_go_package(); + go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.go_package) +} + void FileOptions::set_go_package(const char* value, size_t size) { + set_has_go_package(); + go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.go_package) +} + ::std::string* FileOptions::mutable_go_package() { + set_has_go_package(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.go_package) + return go_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FileOptions::release_go_package() { + clear_has_go_package(); + return go_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_allocated_go_package(::std::string* go_package) { + if (go_package != NULL) { + set_has_go_package(); + } else { + clear_has_go_package(); + } + go_package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), go_package); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.go_package) +} + +// optional bool cc_generic_services = 16 [default = false]; + bool FileOptions::has_cc_generic_services() const { + return (_has_bits_[0] & 0x00000080u) != 0; +} + void FileOptions::set_has_cc_generic_services() { + _has_bits_[0] |= 0x00000080u; +} + void FileOptions::clear_has_cc_generic_services() { + _has_bits_[0] &= ~0x00000080u; +} + void FileOptions::clear_cc_generic_services() { + cc_generic_services_ = false; + clear_has_cc_generic_services(); +} + bool FileOptions::cc_generic_services() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_generic_services) + return cc_generic_services_; +} + void FileOptions::set_cc_generic_services(bool value) { + set_has_cc_generic_services(); + cc_generic_services_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_generic_services) +} + +// optional bool java_generic_services = 17 [default = false]; + bool FileOptions::has_java_generic_services() const { + return (_has_bits_[0] & 0x00000100u) != 0; +} + void FileOptions::set_has_java_generic_services() { + _has_bits_[0] |= 0x00000100u; +} + void FileOptions::clear_has_java_generic_services() { + _has_bits_[0] &= ~0x00000100u; +} + void FileOptions::clear_java_generic_services() { + java_generic_services_ = false; + clear_has_java_generic_services(); +} + bool FileOptions::java_generic_services() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generic_services) + return java_generic_services_; +} + void FileOptions::set_java_generic_services(bool value) { + set_has_java_generic_services(); + java_generic_services_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generic_services) +} + +// optional bool py_generic_services = 18 [default = false]; + bool FileOptions::has_py_generic_services() const { + return (_has_bits_[0] & 0x00000200u) != 0; +} + void FileOptions::set_has_py_generic_services() { + _has_bits_[0] |= 0x00000200u; +} + void FileOptions::clear_has_py_generic_services() { + _has_bits_[0] &= ~0x00000200u; +} + void FileOptions::clear_py_generic_services() { + py_generic_services_ = false; + clear_has_py_generic_services(); +} + bool FileOptions::py_generic_services() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.py_generic_services) + return py_generic_services_; +} + void FileOptions::set_py_generic_services(bool value) { + set_has_py_generic_services(); + py_generic_services_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.py_generic_services) +} + +// optional bool deprecated = 23 [default = false]; + bool FileOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000400u) != 0; +} + void FileOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000400u; +} + void FileOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000400u; +} + void FileOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} + bool FileOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.deprecated) + return deprecated_; +} + void FileOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.deprecated) +} + +// optional bool cc_enable_arenas = 31 [default = false]; + bool FileOptions::has_cc_enable_arenas() const { + return (_has_bits_[0] & 0x00000800u) != 0; +} + void FileOptions::set_has_cc_enable_arenas() { + _has_bits_[0] |= 0x00000800u; +} + void FileOptions::clear_has_cc_enable_arenas() { + _has_bits_[0] &= ~0x00000800u; +} + void FileOptions::clear_cc_enable_arenas() { + cc_enable_arenas_ = false; + clear_has_cc_enable_arenas(); +} + bool FileOptions::cc_enable_arenas() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_enable_arenas) + return cc_enable_arenas_; +} + void FileOptions::set_cc_enable_arenas(bool value) { + set_has_cc_enable_arenas(); + cc_enable_arenas_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_enable_arenas) +} + +// optional string objc_class_prefix = 36; + bool FileOptions::has_objc_class_prefix() const { + return (_has_bits_[0] & 0x00001000u) != 0; +} + void FileOptions::set_has_objc_class_prefix() { + _has_bits_[0] |= 0x00001000u; +} + void FileOptions::clear_has_objc_class_prefix() { + _has_bits_[0] &= ~0x00001000u; +} + void FileOptions::clear_objc_class_prefix() { + objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_objc_class_prefix(); +} + const ::std::string& FileOptions::objc_class_prefix() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.objc_class_prefix) + return objc_class_prefix_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_objc_class_prefix(const ::std::string& value) { + set_has_objc_class_prefix(); + objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.objc_class_prefix) +} + void FileOptions::set_objc_class_prefix(const char* value) { + set_has_objc_class_prefix(); + objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.objc_class_prefix) +} + void FileOptions::set_objc_class_prefix(const char* value, size_t size) { + set_has_objc_class_prefix(); + objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.objc_class_prefix) +} + ::std::string* FileOptions::mutable_objc_class_prefix() { + set_has_objc_class_prefix(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.objc_class_prefix) + return objc_class_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FileOptions::release_objc_class_prefix() { + clear_has_objc_class_prefix(); + return objc_class_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_allocated_objc_class_prefix(::std::string* objc_class_prefix) { + if (objc_class_prefix != NULL) { + set_has_objc_class_prefix(); + } else { + clear_has_objc_class_prefix(); + } + objc_class_prefix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), objc_class_prefix); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.objc_class_prefix) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int FileOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} + void FileOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} + const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.uninterpreted_option) + return uninterpreted_option_.Get(index); +} + ::google::protobuf::UninterpretedOption* FileOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.uninterpreted_option) + return uninterpreted_option_.Mutable(index); +} + ::google::protobuf::UninterpretedOption* FileOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.FileOptions.uninterpreted_option) + return uninterpreted_option_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +FileOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option) + return uninterpreted_option_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +FileOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileOptions.uninterpreted_option) + return &uninterpreted_option_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -5928,19 +8369,17 @@ MessageOptions* MessageOptions::New(::google::protobuf::Arena* arena) const { void MessageOptions::Clear() { _extensions_.Clear(); -#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \ - &reinterpret_cast<MessageOptions*>(16)->f) - \ - reinterpret_cast<char*>(16)) +#define ZR_HELPER_(f) reinterpret_cast<char*>(\ + &reinterpret_cast<MessageOptions*>(16)->f) -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) ZR_(message_set_wire_format_, map_entry_); -#undef OFFSET_OF_FIELD_ +#undef ZR_HELPER_ #undef ZR_ uninterpreted_option_.Clear(); @@ -6266,6 +8705,136 @@ void MessageOptions::InternalSwap(MessageOptions* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// MessageOptions + +// optional bool message_set_wire_format = 1 [default = false]; + bool MessageOptions::has_message_set_wire_format() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void MessageOptions::set_has_message_set_wire_format() { + _has_bits_[0] |= 0x00000001u; +} + void MessageOptions::clear_has_message_set_wire_format() { + _has_bits_[0] &= ~0x00000001u; +} + void MessageOptions::clear_message_set_wire_format() { + message_set_wire_format_ = false; + clear_has_message_set_wire_format(); +} + bool MessageOptions::message_set_wire_format() const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.message_set_wire_format) + return message_set_wire_format_; +} + void MessageOptions::set_message_set_wire_format(bool value) { + set_has_message_set_wire_format(); + message_set_wire_format_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.message_set_wire_format) +} + +// optional bool no_standard_descriptor_accessor = 2 [default = false]; + bool MessageOptions::has_no_standard_descriptor_accessor() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void MessageOptions::set_has_no_standard_descriptor_accessor() { + _has_bits_[0] |= 0x00000002u; +} + void MessageOptions::clear_has_no_standard_descriptor_accessor() { + _has_bits_[0] &= ~0x00000002u; +} + void MessageOptions::clear_no_standard_descriptor_accessor() { + no_standard_descriptor_accessor_ = false; + clear_has_no_standard_descriptor_accessor(); +} + bool MessageOptions::no_standard_descriptor_accessor() const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.no_standard_descriptor_accessor) + return no_standard_descriptor_accessor_; +} + void MessageOptions::set_no_standard_descriptor_accessor(bool value) { + set_has_no_standard_descriptor_accessor(); + no_standard_descriptor_accessor_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.no_standard_descriptor_accessor) +} + +// optional bool deprecated = 3 [default = false]; + bool MessageOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void MessageOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000004u; +} + void MessageOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000004u; +} + void MessageOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} + bool MessageOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.deprecated) + return deprecated_; +} + void MessageOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.deprecated) +} + +// optional bool map_entry = 7; + bool MessageOptions::has_map_entry() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} + void MessageOptions::set_has_map_entry() { + _has_bits_[0] |= 0x00000008u; +} + void MessageOptions::clear_has_map_entry() { + _has_bits_[0] &= ~0x00000008u; +} + void MessageOptions::clear_map_entry() { + map_entry_ = false; + clear_has_map_entry(); +} + bool MessageOptions::map_entry() const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.map_entry) + return map_entry_; +} + void MessageOptions::set_map_entry(bool value) { + set_has_map_entry(); + map_entry_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.map_entry) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int MessageOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} + void MessageOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} + const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.uninterpreted_option) + return uninterpreted_option_.Get(index); +} + ::google::protobuf::UninterpretedOption* MessageOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.MessageOptions.uninterpreted_option) + return uninterpreted_option_.Mutable(index); +} + ::google::protobuf::UninterpretedOption* MessageOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.MessageOptions.uninterpreted_option) + return uninterpreted_option_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +MessageOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option) + return uninterpreted_option_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +MessageOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.MessageOptions.uninterpreted_option) + return &uninterpreted_option_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -6365,21 +8934,19 @@ FieldOptions* FieldOptions::New(::google::protobuf::Arena* arena) const { void FieldOptions::Clear() { _extensions_.Clear(); -#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \ - &reinterpret_cast<FieldOptions*>(16)->f) - \ - reinterpret_cast<char*>(16)) +#define ZR_HELPER_(f) reinterpret_cast<char*>(\ + &reinterpret_cast<FieldOptions*>(16)->f) -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) if (_has_bits_[0 / 32] & 31) { ZR_(ctype_, weak_); } -#undef OFFSET_OF_FIELD_ +#undef ZR_HELPER_ #undef ZR_ uninterpreted_option_.Clear(); @@ -6747,6 +9314,161 @@ void FieldOptions::InternalSwap(FieldOptions* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// FieldOptions + +// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; + bool FieldOptions::has_ctype() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void FieldOptions::set_has_ctype() { + _has_bits_[0] |= 0x00000001u; +} + void FieldOptions::clear_has_ctype() { + _has_bits_[0] &= ~0x00000001u; +} + void FieldOptions::clear_ctype() { + ctype_ = 0; + clear_has_ctype(); +} + ::google::protobuf::FieldOptions_CType FieldOptions::ctype() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.ctype) + return static_cast< ::google::protobuf::FieldOptions_CType >(ctype_); +} + void FieldOptions::set_ctype(::google::protobuf::FieldOptions_CType value) { + assert(::google::protobuf::FieldOptions_CType_IsValid(value)); + set_has_ctype(); + ctype_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.ctype) +} + +// optional bool packed = 2; + bool FieldOptions::has_packed() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void FieldOptions::set_has_packed() { + _has_bits_[0] |= 0x00000002u; +} + void FieldOptions::clear_has_packed() { + _has_bits_[0] &= ~0x00000002u; +} + void FieldOptions::clear_packed() { + packed_ = false; + clear_has_packed(); +} + bool FieldOptions::packed() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.packed) + return packed_; +} + void FieldOptions::set_packed(bool value) { + set_has_packed(); + packed_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.packed) +} + +// optional bool lazy = 5 [default = false]; + bool FieldOptions::has_lazy() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void FieldOptions::set_has_lazy() { + _has_bits_[0] |= 0x00000004u; +} + void FieldOptions::clear_has_lazy() { + _has_bits_[0] &= ~0x00000004u; +} + void FieldOptions::clear_lazy() { + lazy_ = false; + clear_has_lazy(); +} + bool FieldOptions::lazy() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.lazy) + return lazy_; +} + void FieldOptions::set_lazy(bool value) { + set_has_lazy(); + lazy_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.lazy) +} + +// optional bool deprecated = 3 [default = false]; + bool FieldOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} + void FieldOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000008u; +} + void FieldOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000008u; +} + void FieldOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} + bool FieldOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.deprecated) + return deprecated_; +} + void FieldOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.deprecated) +} + +// optional bool weak = 10 [default = false]; + bool FieldOptions::has_weak() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} + void FieldOptions::set_has_weak() { + _has_bits_[0] |= 0x00000010u; +} + void FieldOptions::clear_has_weak() { + _has_bits_[0] &= ~0x00000010u; +} + void FieldOptions::clear_weak() { + weak_ = false; + clear_has_weak(); +} + bool FieldOptions::weak() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.weak) + return weak_; +} + void FieldOptions::set_weak(bool value) { + set_has_weak(); + weak_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.weak) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int FieldOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} + void FieldOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} + const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.uninterpreted_option) + return uninterpreted_option_.Get(index); +} + ::google::protobuf::UninterpretedOption* FieldOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldOptions.uninterpreted_option) + return uninterpreted_option_.Mutable(index); +} + ::google::protobuf::UninterpretedOption* FieldOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.FieldOptions.uninterpreted_option) + return uninterpreted_option_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +FieldOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option) + return uninterpreted_option_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +FieldOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldOptions.uninterpreted_option) + return &uninterpreted_option_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -6817,19 +9539,17 @@ EnumOptions* EnumOptions::New(::google::protobuf::Arena* arena) const { void EnumOptions::Clear() { _extensions_.Clear(); -#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \ - &reinterpret_cast<EnumOptions*>(16)->f) - \ - reinterpret_cast<char*>(16)) +#define ZR_HELPER_(f) reinterpret_cast<char*>(\ + &reinterpret_cast<EnumOptions*>(16)->f) -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) ZR_(allow_alias_, deprecated_); -#undef OFFSET_OF_FIELD_ +#undef ZR_HELPER_ #undef ZR_ uninterpreted_option_.Clear(); @@ -7087,6 +9807,88 @@ void EnumOptions::InternalSwap(EnumOptions* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// EnumOptions + +// optional bool allow_alias = 2; + bool EnumOptions::has_allow_alias() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void EnumOptions::set_has_allow_alias() { + _has_bits_[0] |= 0x00000001u; +} + void EnumOptions::clear_has_allow_alias() { + _has_bits_[0] &= ~0x00000001u; +} + void EnumOptions::clear_allow_alias() { + allow_alias_ = false; + clear_has_allow_alias(); +} + bool EnumOptions::allow_alias() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.allow_alias) + return allow_alias_; +} + void EnumOptions::set_allow_alias(bool value) { + set_has_allow_alias(); + allow_alias_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.allow_alias) +} + +// optional bool deprecated = 3 [default = false]; + bool EnumOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void EnumOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000002u; +} + void EnumOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000002u; +} + void EnumOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} + bool EnumOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.deprecated) + return deprecated_; +} + void EnumOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.deprecated) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int EnumOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} + void EnumOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} + const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.uninterpreted_option) + return uninterpreted_option_.Get(index); +} + ::google::protobuf::UninterpretedOption* EnumOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumOptions.uninterpreted_option) + return uninterpreted_option_.Mutable(index); +} + ::google::protobuf::UninterpretedOption* EnumOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.EnumOptions.uninterpreted_option) + return uninterpreted_option_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +EnumOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option) + return uninterpreted_option_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +EnumOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumOptions.uninterpreted_option) + return &uninterpreted_option_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -7375,6 +10177,64 @@ void EnumValueOptions::InternalSwap(EnumValueOptions* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// EnumValueOptions + +// optional bool deprecated = 1 [default = false]; + bool EnumValueOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void EnumValueOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000001u; +} + void EnumValueOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000001u; +} + void EnumValueOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} + bool EnumValueOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.deprecated) + return deprecated_; +} + void EnumValueOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.EnumValueOptions.deprecated) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int EnumValueOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} + void EnumValueOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} + const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.uninterpreted_option) + return uninterpreted_option_.Get(index); +} + ::google::protobuf::UninterpretedOption* EnumValueOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueOptions.uninterpreted_option) + return uninterpreted_option_.Mutable(index); +} + ::google::protobuf::UninterpretedOption* EnumValueOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.EnumValueOptions.uninterpreted_option) + return uninterpreted_option_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +EnumValueOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option) + return uninterpreted_option_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +EnumValueOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValueOptions.uninterpreted_option) + return &uninterpreted_option_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -7663,6 +10523,64 @@ void ServiceOptions::InternalSwap(ServiceOptions* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// ServiceOptions + +// optional bool deprecated = 33 [default = false]; + bool ServiceOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void ServiceOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000001u; +} + void ServiceOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000001u; +} + void ServiceOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} + bool ServiceOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.deprecated) + return deprecated_; +} + void ServiceOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.ServiceOptions.deprecated) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int ServiceOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} + void ServiceOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} + const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.uninterpreted_option) + return uninterpreted_option_.Get(index); +} + ::google::protobuf::UninterpretedOption* ServiceOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceOptions.uninterpreted_option) + return uninterpreted_option_.Mutable(index); +} + ::google::protobuf::UninterpretedOption* ServiceOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.ServiceOptions.uninterpreted_option) + return uninterpreted_option_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +ServiceOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option) + return uninterpreted_option_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +ServiceOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceOptions.uninterpreted_option) + return &uninterpreted_option_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -7951,6 +10869,64 @@ void MethodOptions::InternalSwap(MethodOptions* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// MethodOptions + +// optional bool deprecated = 33 [default = false]; + bool MethodOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void MethodOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000001u; +} + void MethodOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000001u; +} + void MethodOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} + bool MethodOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.deprecated) + return deprecated_; +} + void MethodOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MethodOptions.deprecated) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int MethodOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} + void MethodOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} + const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.uninterpreted_option) + return uninterpreted_option_.Get(index); +} + ::google::protobuf::UninterpretedOption* MethodOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodOptions.uninterpreted_option) + return uninterpreted_option_.Mutable(index); +} + ::google::protobuf::UninterpretedOption* MethodOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.MethodOptions.uninterpreted_option) + return uninterpreted_option_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +MethodOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option) + return uninterpreted_option_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +MethodOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.MethodOptions.uninterpreted_option) + return &uninterpreted_option_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -8338,15 +11314,13 @@ UninterpretedOption* UninterpretedOption::New(::google::protobuf::Arena* arena) } void UninterpretedOption::Clear() { -#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \ - &reinterpret_cast<UninterpretedOption*>(16)->f) - \ - reinterpret_cast<char*>(16)) +#define ZR_HELPER_(f) reinterpret_cast<char*>(\ + &reinterpret_cast<UninterpretedOption*>(16)->f) -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) if (_has_bits_[0 / 32] & 126) { ZR_(positive_int_value_, double_value_); @@ -8361,7 +11335,7 @@ void UninterpretedOption::Clear() { } } -#undef OFFSET_OF_FIELD_ +#undef ZR_HELPER_ #undef ZR_ name_.Clear(); @@ -8778,6 +11752,352 @@ void UninterpretedOption::InternalSwap(UninterpretedOption* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// UninterpretedOption_NamePart + +// required string name_part = 1; + bool UninterpretedOption_NamePart::has_name_part() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void UninterpretedOption_NamePart::set_has_name_part() { + _has_bits_[0] |= 0x00000001u; +} + void UninterpretedOption_NamePart::clear_has_name_part() { + _has_bits_[0] &= ~0x00000001u; +} + void UninterpretedOption_NamePart::clear_name_part() { + name_part_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name_part(); +} + const ::std::string& UninterpretedOption_NamePart::name_part() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.name_part) + return name_part_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void UninterpretedOption_NamePart::set_name_part(const ::std::string& value) { + set_has_name_part(); + name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.name_part) +} + void UninterpretedOption_NamePart::set_name_part(const char* value) { + set_has_name_part(); + name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.NamePart.name_part) +} + void UninterpretedOption_NamePart::set_name_part(const char* value, size_t size) { + set_has_name_part(); + name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.NamePart.name_part) +} + ::std::string* UninterpretedOption_NamePart::mutable_name_part() { + set_has_name_part(); + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.NamePart.name_part) + return name_part_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* UninterpretedOption_NamePart::release_name_part() { + clear_has_name_part(); + return name_part_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void UninterpretedOption_NamePart::set_allocated_name_part(::std::string* name_part) { + if (name_part != NULL) { + set_has_name_part(); + } else { + clear_has_name_part(); + } + name_part_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name_part); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.NamePart.name_part) +} + +// required bool is_extension = 2; + bool UninterpretedOption_NamePart::has_is_extension() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void UninterpretedOption_NamePart::set_has_is_extension() { + _has_bits_[0] |= 0x00000002u; +} + void UninterpretedOption_NamePart::clear_has_is_extension() { + _has_bits_[0] &= ~0x00000002u; +} + void UninterpretedOption_NamePart::clear_is_extension() { + is_extension_ = false; + clear_has_is_extension(); +} + bool UninterpretedOption_NamePart::is_extension() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.is_extension) + return is_extension_; +} + void UninterpretedOption_NamePart::set_is_extension(bool value) { + set_has_is_extension(); + is_extension_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.is_extension) +} + +// ------------------------------------------------------------------- + +// UninterpretedOption + +// repeated .google.protobuf.UninterpretedOption.NamePart name = 2; + int UninterpretedOption::name_size() const { + return name_.size(); +} + void UninterpretedOption::clear_name() { + name_.Clear(); +} + const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.name) + return name_.Get(index); +} + ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::mutable_name(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.name) + return name_.Mutable(index); +} + ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::add_name() { + // @@protoc_insertion_point(field_add:google.protobuf.UninterpretedOption.name) + return name_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >& +UninterpretedOption::name() const { + // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name) + return name_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >* +UninterpretedOption::mutable_name() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.UninterpretedOption.name) + return &name_; +} + +// optional string identifier_value = 3; + bool UninterpretedOption::has_identifier_value() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void UninterpretedOption::set_has_identifier_value() { + _has_bits_[0] |= 0x00000002u; +} + void UninterpretedOption::clear_has_identifier_value() { + _has_bits_[0] &= ~0x00000002u; +} + void UninterpretedOption::clear_identifier_value() { + identifier_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_identifier_value(); +} + const ::std::string& UninterpretedOption::identifier_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.identifier_value) + return identifier_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void UninterpretedOption::set_identifier_value(const ::std::string& value) { + set_has_identifier_value(); + identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.identifier_value) +} + void UninterpretedOption::set_identifier_value(const char* value) { + set_has_identifier_value(); + identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.identifier_value) +} + void UninterpretedOption::set_identifier_value(const char* value, size_t size) { + set_has_identifier_value(); + identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.identifier_value) +} + ::std::string* UninterpretedOption::mutable_identifier_value() { + set_has_identifier_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.identifier_value) + return identifier_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* UninterpretedOption::release_identifier_value() { + clear_has_identifier_value(); + return identifier_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void UninterpretedOption::set_allocated_identifier_value(::std::string* identifier_value) { + if (identifier_value != NULL) { + set_has_identifier_value(); + } else { + clear_has_identifier_value(); + } + identifier_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), identifier_value); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.identifier_value) +} + +// optional uint64 positive_int_value = 4; + bool UninterpretedOption::has_positive_int_value() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void UninterpretedOption::set_has_positive_int_value() { + _has_bits_[0] |= 0x00000004u; +} + void UninterpretedOption::clear_has_positive_int_value() { + _has_bits_[0] &= ~0x00000004u; +} + void UninterpretedOption::clear_positive_int_value() { + positive_int_value_ = GOOGLE_ULONGLONG(0); + clear_has_positive_int_value(); +} + ::google::protobuf::uint64 UninterpretedOption::positive_int_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.positive_int_value) + return positive_int_value_; +} + void UninterpretedOption::set_positive_int_value(::google::protobuf::uint64 value) { + set_has_positive_int_value(); + positive_int_value_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.positive_int_value) +} + +// optional int64 negative_int_value = 5; + bool UninterpretedOption::has_negative_int_value() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} + void UninterpretedOption::set_has_negative_int_value() { + _has_bits_[0] |= 0x00000008u; +} + void UninterpretedOption::clear_has_negative_int_value() { + _has_bits_[0] &= ~0x00000008u; +} + void UninterpretedOption::clear_negative_int_value() { + negative_int_value_ = GOOGLE_LONGLONG(0); + clear_has_negative_int_value(); +} + ::google::protobuf::int64 UninterpretedOption::negative_int_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.negative_int_value) + return negative_int_value_; +} + void UninterpretedOption::set_negative_int_value(::google::protobuf::int64 value) { + set_has_negative_int_value(); + negative_int_value_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.negative_int_value) +} + +// optional double double_value = 6; + bool UninterpretedOption::has_double_value() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} + void UninterpretedOption::set_has_double_value() { + _has_bits_[0] |= 0x00000010u; +} + void UninterpretedOption::clear_has_double_value() { + _has_bits_[0] &= ~0x00000010u; +} + void UninterpretedOption::clear_double_value() { + double_value_ = 0; + clear_has_double_value(); +} + double UninterpretedOption::double_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.double_value) + return double_value_; +} + void UninterpretedOption::set_double_value(double value) { + set_has_double_value(); + double_value_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.double_value) +} + +// optional bytes string_value = 7; + bool UninterpretedOption::has_string_value() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} + void UninterpretedOption::set_has_string_value() { + _has_bits_[0] |= 0x00000020u; +} + void UninterpretedOption::clear_has_string_value() { + _has_bits_[0] &= ~0x00000020u; +} + void UninterpretedOption::clear_string_value() { + string_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_string_value(); +} + const ::std::string& UninterpretedOption::string_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.string_value) + return string_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void UninterpretedOption::set_string_value(const ::std::string& value) { + set_has_string_value(); + string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.string_value) +} + void UninterpretedOption::set_string_value(const char* value) { + set_has_string_value(); + string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.string_value) +} + void UninterpretedOption::set_string_value(const void* value, size_t size) { + set_has_string_value(); + string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.string_value) +} + ::std::string* UninterpretedOption::mutable_string_value() { + set_has_string_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.string_value) + return string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* UninterpretedOption::release_string_value() { + clear_has_string_value(); + return string_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void UninterpretedOption::set_allocated_string_value(::std::string* string_value) { + if (string_value != NULL) { + set_has_string_value(); + } else { + clear_has_string_value(); + } + string_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), string_value); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.string_value) +} + +// optional string aggregate_value = 8; + bool UninterpretedOption::has_aggregate_value() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} + void UninterpretedOption::set_has_aggregate_value() { + _has_bits_[0] |= 0x00000040u; +} + void UninterpretedOption::clear_has_aggregate_value() { + _has_bits_[0] &= ~0x00000040u; +} + void UninterpretedOption::clear_aggregate_value() { + aggregate_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_aggregate_value(); +} + const ::std::string& UninterpretedOption::aggregate_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.aggregate_value) + return aggregate_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void UninterpretedOption::set_aggregate_value(const ::std::string& value) { + set_has_aggregate_value(); + aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.aggregate_value) +} + void UninterpretedOption::set_aggregate_value(const char* value) { + set_has_aggregate_value(); + aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.aggregate_value) +} + void UninterpretedOption::set_aggregate_value(const char* value, size_t size) { + set_has_aggregate_value(); + aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.aggregate_value) +} + ::std::string* UninterpretedOption::mutable_aggregate_value() { + set_has_aggregate_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.aggregate_value) + return aggregate_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* UninterpretedOption::release_aggregate_value() { + clear_has_aggregate_value(); + return aggregate_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void UninterpretedOption::set_allocated_aggregate_value(::std::string* aggregate_value) { + if (aggregate_value != NULL) { + set_has_aggregate_value(); + } else { + clear_has_aggregate_value(); + } + aggregate_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), aggregate_value); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.aggregate_value) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -8786,6 +12106,7 @@ const int SourceCodeInfo_Location::kPathFieldNumber; const int SourceCodeInfo_Location::kSpanFieldNumber; const int SourceCodeInfo_Location::kLeadingCommentsFieldNumber; const int SourceCodeInfo_Location::kTrailingCommentsFieldNumber; +const int SourceCodeInfo_Location::kLeadingDetachedCommentsFieldNumber; #endif // !_MSC_VER SourceCodeInfo_Location::SourceCodeInfo_Location() @@ -8861,6 +12182,7 @@ void SourceCodeInfo_Location::Clear() { } path_.Clear(); span_.Clear(); + leading_detached_comments_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); if (_internal_metadata_.have_unknown_fields()) { mutable_unknown_fields()->Clear(); @@ -8942,6 +12264,25 @@ bool SourceCodeInfo_Location::MergePartialFromCodedStream( } else { goto handle_unusual; } + if (input->ExpectTag(50)) goto parse_leading_detached_comments; + break; + } + + // repeated string leading_detached_comments = 6; + case 6: { + if (tag == 50) { + parse_leading_detached_comments: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->add_leading_detached_comments())); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->leading_detached_comments(this->leading_detached_comments_size() - 1).data(), + this->leading_detached_comments(this->leading_detached_comments_size() - 1).length(), + ::google::protobuf::internal::WireFormat::PARSE, + "google.protobuf.SourceCodeInfo.Location.leading_detached_comments"); + } else { + goto handle_unusual; + } + if (input->ExpectTag(50)) goto parse_leading_detached_comments; if (input->ExpectAtEnd()) goto success; break; } @@ -9011,6 +12352,16 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes( 4, this->trailing_comments(), output); } + // repeated string leading_detached_comments = 6; + for (int i = 0; i < this->leading_detached_comments_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->leading_detached_comments(i).data(), this->leading_detached_comments(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.SourceCodeInfo.Location.leading_detached_comments"); + ::google::protobuf::internal::WireFormatLite::WriteString( + 6, this->leading_detached_comments(i), output); + } + if (_internal_metadata_.have_unknown_fields()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); @@ -9071,6 +12422,16 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes( 4, this->trailing_comments(), target); } + // repeated string leading_detached_comments = 6; + for (int i = 0; i < this->leading_detached_comments_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->leading_detached_comments(i).data(), this->leading_detached_comments(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.SourceCodeInfo.Location.leading_detached_comments"); + target = ::google::protobuf::internal::WireFormatLite:: + WriteStringToArray(6, this->leading_detached_comments(i), target); + } + if (_internal_metadata_.have_unknown_fields()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); @@ -9132,6 +12493,13 @@ int SourceCodeInfo_Location::ByteSize() const { total_size += data_size; } + // repeated string leading_detached_comments = 6; + total_size += 1 * this->leading_detached_comments_size(); + for (int i = 0; i < this->leading_detached_comments_size(); i++) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this->leading_detached_comments(i)); + } + if (_internal_metadata_.have_unknown_fields()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -9159,6 +12527,7 @@ void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); path_.MergeFrom(from.path_); span_.MergeFrom(from.span_); + leading_detached_comments_.MergeFrom(from.leading_detached_comments_); if (from._has_bits_[2 / 32] & (0xffu << (2 % 32))) { if (from.has_leading_comments()) { set_has_leading_comments(); @@ -9200,6 +12569,7 @@ void SourceCodeInfo_Location::InternalSwap(SourceCodeInfo_Location* other) { span_.UnsafeArenaSwap(&other->span_); leading_comments_.Swap(&other->leading_comments_); trailing_comments_.Swap(&other->trailing_comments_); + leading_detached_comments_.UnsafeArenaSwap(&other->leading_detached_comments_); std::swap(_has_bits_[0], other->_has_bits_[0]); _internal_metadata_.Swap(&other->_internal_metadata_); std::swap(_cached_size_, other->_cached_size_); @@ -9443,6 +12813,264 @@ void SourceCodeInfo::InternalSwap(SourceCodeInfo* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// SourceCodeInfo_Location + +// repeated int32 path = 1 [packed = true]; + int SourceCodeInfo_Location::path_size() const { + return path_.size(); +} + void SourceCodeInfo_Location::clear_path() { + path_.Clear(); +} + ::google::protobuf::int32 SourceCodeInfo_Location::path(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.path) + return path_.Get(index); +} + void SourceCodeInfo_Location::set_path(int index, ::google::protobuf::int32 value) { + path_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.path) +} + void SourceCodeInfo_Location::add_path(::google::protobuf::int32 value) { + path_.Add(value); + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.path) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +SourceCodeInfo_Location::path() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.path) + return path_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +SourceCodeInfo_Location::mutable_path() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.path) + return &path_; +} + +// repeated int32 span = 2 [packed = true]; + int SourceCodeInfo_Location::span_size() const { + return span_.size(); +} + void SourceCodeInfo_Location::clear_span() { + span_.Clear(); +} + ::google::protobuf::int32 SourceCodeInfo_Location::span(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.span) + return span_.Get(index); +} + void SourceCodeInfo_Location::set_span(int index, ::google::protobuf::int32 value) { + span_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.span) +} + void SourceCodeInfo_Location::add_span(::google::protobuf::int32 value) { + span_.Add(value); + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.span) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +SourceCodeInfo_Location::span() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.span) + return span_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +SourceCodeInfo_Location::mutable_span() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.span) + return &span_; +} + +// optional string leading_comments = 3; + bool SourceCodeInfo_Location::has_leading_comments() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void SourceCodeInfo_Location::set_has_leading_comments() { + _has_bits_[0] |= 0x00000004u; +} + void SourceCodeInfo_Location::clear_has_leading_comments() { + _has_bits_[0] &= ~0x00000004u; +} + void SourceCodeInfo_Location::clear_leading_comments() { + leading_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_leading_comments(); +} + const ::std::string& SourceCodeInfo_Location::leading_comments() const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_comments) + return leading_comments_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void SourceCodeInfo_Location::set_leading_comments(const ::std::string& value) { + set_has_leading_comments(); + leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_comments) +} + void SourceCodeInfo_Location::set_leading_comments(const char* value) { + set_has_leading_comments(); + leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_comments) +} + void SourceCodeInfo_Location::set_leading_comments(const char* value, size_t size) { + set_has_leading_comments(); + leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_comments) +} + ::std::string* SourceCodeInfo_Location::mutable_leading_comments() { + set_has_leading_comments(); + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_comments) + return leading_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* SourceCodeInfo_Location::release_leading_comments() { + clear_has_leading_comments(); + return leading_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void SourceCodeInfo_Location::set_allocated_leading_comments(::std::string* leading_comments) { + if (leading_comments != NULL) { + set_has_leading_comments(); + } else { + clear_has_leading_comments(); + } + leading_comments_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), leading_comments); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.leading_comments) +} + +// optional string trailing_comments = 4; + bool SourceCodeInfo_Location::has_trailing_comments() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} + void SourceCodeInfo_Location::set_has_trailing_comments() { + _has_bits_[0] |= 0x00000008u; +} + void SourceCodeInfo_Location::clear_has_trailing_comments() { + _has_bits_[0] &= ~0x00000008u; +} + void SourceCodeInfo_Location::clear_trailing_comments() { + trailing_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_trailing_comments(); +} + const ::std::string& SourceCodeInfo_Location::trailing_comments() const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.trailing_comments) + return trailing_comments_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void SourceCodeInfo_Location::set_trailing_comments(const ::std::string& value) { + set_has_trailing_comments(); + trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.trailing_comments) +} + void SourceCodeInfo_Location::set_trailing_comments(const char* value) { + set_has_trailing_comments(); + trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.trailing_comments) +} + void SourceCodeInfo_Location::set_trailing_comments(const char* value, size_t size) { + set_has_trailing_comments(); + trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.trailing_comments) +} + ::std::string* SourceCodeInfo_Location::mutable_trailing_comments() { + set_has_trailing_comments(); + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.trailing_comments) + return trailing_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* SourceCodeInfo_Location::release_trailing_comments() { + clear_has_trailing_comments(); + return trailing_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::string* trailing_comments) { + if (trailing_comments != NULL) { + set_has_trailing_comments(); + } else { + clear_has_trailing_comments(); + } + trailing_comments_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), trailing_comments); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments) +} + +// repeated string leading_detached_comments = 6; + int SourceCodeInfo_Location::leading_detached_comments_size() const { + return leading_detached_comments_.size(); +} + void SourceCodeInfo_Location::clear_leading_detached_comments() { + leading_detached_comments_.Clear(); +} + const ::std::string& SourceCodeInfo_Location::leading_detached_comments(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return leading_detached_comments_.Get(index); +} + ::std::string* SourceCodeInfo_Location::mutable_leading_detached_comments(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return leading_detached_comments_.Mutable(index); +} + void SourceCodeInfo_Location::set_leading_detached_comments(int index, const ::std::string& value) { + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + leading_detached_comments_.Mutable(index)->assign(value); +} + void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value) { + leading_detached_comments_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} + void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value, size_t size) { + leading_detached_comments_.Mutable(index)->assign( + reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} + ::std::string* SourceCodeInfo_Location::add_leading_detached_comments() { + return leading_detached_comments_.Add(); +} + void SourceCodeInfo_Location::add_leading_detached_comments(const ::std::string& value) { + leading_detached_comments_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} + void SourceCodeInfo_Location::add_leading_detached_comments(const char* value) { + leading_detached_comments_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} + void SourceCodeInfo_Location::add_leading_detached_comments(const char* value, size_t size) { + leading_detached_comments_.Add()->assign(reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} + const ::google::protobuf::RepeatedPtrField< ::std::string>& +SourceCodeInfo_Location::leading_detached_comments() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return leading_detached_comments_; +} + ::google::protobuf::RepeatedPtrField< ::std::string>* +SourceCodeInfo_Location::mutable_leading_detached_comments() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return &leading_detached_comments_; +} + +// ------------------------------------------------------------------- + +// SourceCodeInfo + +// repeated .google.protobuf.SourceCodeInfo.Location location = 1; + int SourceCodeInfo::location_size() const { + return location_.size(); +} + void SourceCodeInfo::clear_location() { + location_.Clear(); +} + const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.location) + return location_.Get(index); +} + ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::mutable_location(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.location) + return location_.Mutable(index); +} + ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location() { + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.location) + return location_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& +SourceCodeInfo::location() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location) + return location_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >* +SourceCodeInfo::mutable_location() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.location) + return &location_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index 6bb5c6a6..d8cba659 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -8,12 +8,12 @@ #include <google/protobuf/stubs/common.h> -#if GOOGLE_PROTOBUF_VERSION < 2006000 +#if GOOGLE_PROTOBUF_VERSION < 3000000 #error This file was generated by a newer version of protoc which is #error incompatible with your Protocol Buffer headers. Please update #error your headers. #endif -#if 2006002 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION #error This file was generated by an older version of protoc which is #error incompatible with your Protocol Buffer headers. Please #error regenerate this file with a newer version of protoc. @@ -222,15 +222,15 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message // accessors ------------------------------------------------------- // repeated .google.protobuf.FileDescriptorProto file = 1; - inline int file_size() const; - inline void clear_file(); + int file_size() const; + void clear_file(); static const int kFileFieldNumber = 1; - inline const ::google::protobuf::FileDescriptorProto& file(int index) const; - inline ::google::protobuf::FileDescriptorProto* mutable_file(int index); - inline ::google::protobuf::FileDescriptorProto* add_file(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& + const ::google::protobuf::FileDescriptorProto& file(int index) const; + ::google::protobuf::FileDescriptorProto* mutable_file(int index); + ::google::protobuf::FileDescriptorProto* add_file(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& file() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* mutable_file(); // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet) @@ -314,146 +314,146 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag // accessors ------------------------------------------------------- // optional string name = 1; - inline bool has_name() const; - inline void clear_name(); + bool has_name() const; + void clear_name(); static const int kNameFieldNumber = 1; - inline const ::std::string& name() const; - inline void set_name(const ::std::string& value); - inline void set_name(const char* value); - inline void set_name(const char* value, size_t size); - inline ::std::string* mutable_name(); - inline ::std::string* release_name(); - inline void set_allocated_name(::std::string* name); + const ::std::string& name() const; + void set_name(const ::std::string& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + ::std::string* mutable_name(); + ::std::string* release_name(); + void set_allocated_name(::std::string* name); // optional string package = 2; - inline bool has_package() const; - inline void clear_package(); + bool has_package() const; + void clear_package(); static const int kPackageFieldNumber = 2; - inline const ::std::string& package() const; - inline void set_package(const ::std::string& value); - inline void set_package(const char* value); - inline void set_package(const char* value, size_t size); - inline ::std::string* mutable_package(); - inline ::std::string* release_package(); - inline void set_allocated_package(::std::string* package); + const ::std::string& package() const; + void set_package(const ::std::string& value); + void set_package(const char* value); + void set_package(const char* value, size_t size); + ::std::string* mutable_package(); + ::std::string* release_package(); + void set_allocated_package(::std::string* package); // repeated string dependency = 3; - inline int dependency_size() const; - inline void clear_dependency(); + int dependency_size() const; + void clear_dependency(); static const int kDependencyFieldNumber = 3; - inline const ::std::string& dependency(int index) const; - inline ::std::string* mutable_dependency(int index); - inline void set_dependency(int index, const ::std::string& value); - inline void set_dependency(int index, const char* value); - inline void set_dependency(int index, const char* value, size_t size); - inline ::std::string* add_dependency(); - inline void add_dependency(const ::std::string& value); - inline void add_dependency(const char* value); - inline void add_dependency(const char* value, size_t size); - inline const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const; - inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency(); + const ::std::string& dependency(int index) const; + ::std::string* mutable_dependency(int index); + void set_dependency(int index, const ::std::string& value); + void set_dependency(int index, const char* value); + void set_dependency(int index, const char* value, size_t size); + ::std::string* add_dependency(); + void add_dependency(const ::std::string& value); + void add_dependency(const char* value); + void add_dependency(const char* value, size_t size); + const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const; + ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency(); // repeated int32 public_dependency = 10; - inline int public_dependency_size() const; - inline void clear_public_dependency(); + int public_dependency_size() const; + void clear_public_dependency(); static const int kPublicDependencyFieldNumber = 10; - inline ::google::protobuf::int32 public_dependency(int index) const; - inline void set_public_dependency(int index, ::google::protobuf::int32 value); - inline void add_public_dependency(::google::protobuf::int32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + ::google::protobuf::int32 public_dependency(int index) const; + void set_public_dependency(int index, ::google::protobuf::int32 value); + void add_public_dependency(::google::protobuf::int32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& public_dependency() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* mutable_public_dependency(); // repeated int32 weak_dependency = 11; - inline int weak_dependency_size() const; - inline void clear_weak_dependency(); + int weak_dependency_size() const; + void clear_weak_dependency(); static const int kWeakDependencyFieldNumber = 11; - inline ::google::protobuf::int32 weak_dependency(int index) const; - inline void set_weak_dependency(int index, ::google::protobuf::int32 value); - inline void add_weak_dependency(::google::protobuf::int32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + ::google::protobuf::int32 weak_dependency(int index) const; + void set_weak_dependency(int index, ::google::protobuf::int32 value); + void add_weak_dependency(::google::protobuf::int32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& weak_dependency() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* mutable_weak_dependency(); // repeated .google.protobuf.DescriptorProto message_type = 4; - inline int message_type_size() const; - inline void clear_message_type(); + int message_type_size() const; + void clear_message_type(); static const int kMessageTypeFieldNumber = 4; - inline const ::google::protobuf::DescriptorProto& message_type(int index) const; - inline ::google::protobuf::DescriptorProto* mutable_message_type(int index); - inline ::google::protobuf::DescriptorProto* add_message_type(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& + const ::google::protobuf::DescriptorProto& message_type(int index) const; + ::google::protobuf::DescriptorProto* mutable_message_type(int index); + ::google::protobuf::DescriptorProto* add_message_type(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& message_type() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* mutable_message_type(); // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; - inline int enum_type_size() const; - inline void clear_enum_type(); + int enum_type_size() const; + void clear_enum_type(); static const int kEnumTypeFieldNumber = 5; - inline const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const; - inline ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index); - inline ::google::protobuf::EnumDescriptorProto* add_enum_type(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& + const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const; + ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index); + ::google::protobuf::EnumDescriptorProto* add_enum_type(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& enum_type() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* mutable_enum_type(); // repeated .google.protobuf.ServiceDescriptorProto service = 6; - inline int service_size() const; - inline void clear_service(); + int service_size() const; + void clear_service(); static const int kServiceFieldNumber = 6; - inline const ::google::protobuf::ServiceDescriptorProto& service(int index) const; - inline ::google::protobuf::ServiceDescriptorProto* mutable_service(int index); - inline ::google::protobuf::ServiceDescriptorProto* add_service(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >& + const ::google::protobuf::ServiceDescriptorProto& service(int index) const; + ::google::protobuf::ServiceDescriptorProto* mutable_service(int index); + ::google::protobuf::ServiceDescriptorProto* add_service(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >& service() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >* mutable_service(); // repeated .google.protobuf.FieldDescriptorProto extension = 7; - inline int extension_size() const; - inline void clear_extension(); + int extension_size() const; + void clear_extension(); static const int kExtensionFieldNumber = 7; - inline const ::google::protobuf::FieldDescriptorProto& extension(int index) const; - inline ::google::protobuf::FieldDescriptorProto* mutable_extension(int index); - inline ::google::protobuf::FieldDescriptorProto* add_extension(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& + const ::google::protobuf::FieldDescriptorProto& extension(int index) const; + ::google::protobuf::FieldDescriptorProto* mutable_extension(int index); + ::google::protobuf::FieldDescriptorProto* add_extension(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& extension() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* mutable_extension(); // optional .google.protobuf.FileOptions options = 8; - inline bool has_options() const; - inline void clear_options(); + bool has_options() const; + void clear_options(); static const int kOptionsFieldNumber = 8; - inline const ::google::protobuf::FileOptions& options() const; - inline ::google::protobuf::FileOptions* mutable_options(); - inline ::google::protobuf::FileOptions* release_options(); - inline void set_allocated_options(::google::protobuf::FileOptions* options); + const ::google::protobuf::FileOptions& options() const; + ::google::protobuf::FileOptions* mutable_options(); + ::google::protobuf::FileOptions* release_options(); + void set_allocated_options(::google::protobuf::FileOptions* options); // optional .google.protobuf.SourceCodeInfo source_code_info = 9; - inline bool has_source_code_info() const; - inline void clear_source_code_info(); + bool has_source_code_info() const; + void clear_source_code_info(); static const int kSourceCodeInfoFieldNumber = 9; - inline const ::google::protobuf::SourceCodeInfo& source_code_info() const; - inline ::google::protobuf::SourceCodeInfo* mutable_source_code_info(); - inline ::google::protobuf::SourceCodeInfo* release_source_code_info(); - inline void set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info); + const ::google::protobuf::SourceCodeInfo& source_code_info() const; + ::google::protobuf::SourceCodeInfo* mutable_source_code_info(); + ::google::protobuf::SourceCodeInfo* release_source_code_info(); + void set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info); // optional string syntax = 12; - inline bool has_syntax() const; - inline void clear_syntax(); + bool has_syntax() const; + void clear_syntax(); static const int kSyntaxFieldNumber = 12; - inline const ::std::string& syntax() const; - inline void set_syntax(const ::std::string& value); - inline void set_syntax(const char* value); - inline void set_syntax(const char* value, size_t size); - inline ::std::string* mutable_syntax(); - inline ::std::string* release_syntax(); - inline void set_allocated_syntax(::std::string* syntax); + const ::std::string& syntax() const; + void set_syntax(const ::std::string& value); + void set_syntax(const char* value); + void set_syntax(const char* value, size_t size); + ::std::string* mutable_syntax(); + ::std::string* release_syntax(); + void set_allocated_syntax(::std::string* syntax); // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto) private: @@ -557,18 +557,18 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto // accessors ------------------------------------------------------- // optional int32 start = 1; - inline bool has_start() const; - inline void clear_start(); + bool has_start() const; + void clear_start(); static const int kStartFieldNumber = 1; - inline ::google::protobuf::int32 start() const; - inline void set_start(::google::protobuf::int32 value); + ::google::protobuf::int32 start() const; + void set_start(::google::protobuf::int32 value); // optional int32 end = 2; - inline bool has_end() const; - inline void clear_end(); + bool has_end() const; + void clear_end(); static const int kEndFieldNumber = 2; - inline ::google::protobuf::int32 end() const; - inline void set_end(::google::protobuf::int32 value); + ::google::protobuf::int32 end() const; + void set_end(::google::protobuf::int32 value); // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange) private: @@ -658,97 +658,97 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // optional string name = 1; - inline bool has_name() const; - inline void clear_name(); + bool has_name() const; + void clear_name(); static const int kNameFieldNumber = 1; - inline const ::std::string& name() const; - inline void set_name(const ::std::string& value); - inline void set_name(const char* value); - inline void set_name(const char* value, size_t size); - inline ::std::string* mutable_name(); - inline ::std::string* release_name(); - inline void set_allocated_name(::std::string* name); + const ::std::string& name() const; + void set_name(const ::std::string& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + ::std::string* mutable_name(); + ::std::string* release_name(); + void set_allocated_name(::std::string* name); // repeated .google.protobuf.FieldDescriptorProto field = 2; - inline int field_size() const; - inline void clear_field(); + int field_size() const; + void clear_field(); static const int kFieldFieldNumber = 2; - inline const ::google::protobuf::FieldDescriptorProto& field(int index) const; - inline ::google::protobuf::FieldDescriptorProto* mutable_field(int index); - inline ::google::protobuf::FieldDescriptorProto* add_field(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& + const ::google::protobuf::FieldDescriptorProto& field(int index) const; + ::google::protobuf::FieldDescriptorProto* mutable_field(int index); + ::google::protobuf::FieldDescriptorProto* add_field(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& field() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* mutable_field(); // repeated .google.protobuf.FieldDescriptorProto extension = 6; - inline int extension_size() const; - inline void clear_extension(); + int extension_size() const; + void clear_extension(); static const int kExtensionFieldNumber = 6; - inline const ::google::protobuf::FieldDescriptorProto& extension(int index) const; - inline ::google::protobuf::FieldDescriptorProto* mutable_extension(int index); - inline ::google::protobuf::FieldDescriptorProto* add_extension(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& + const ::google::protobuf::FieldDescriptorProto& extension(int index) const; + ::google::protobuf::FieldDescriptorProto* mutable_extension(int index); + ::google::protobuf::FieldDescriptorProto* add_extension(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& extension() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* mutable_extension(); // repeated .google.protobuf.DescriptorProto nested_type = 3; - inline int nested_type_size() const; - inline void clear_nested_type(); + int nested_type_size() const; + void clear_nested_type(); static const int kNestedTypeFieldNumber = 3; - inline const ::google::protobuf::DescriptorProto& nested_type(int index) const; - inline ::google::protobuf::DescriptorProto* mutable_nested_type(int index); - inline ::google::protobuf::DescriptorProto* add_nested_type(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& + const ::google::protobuf::DescriptorProto& nested_type(int index) const; + ::google::protobuf::DescriptorProto* mutable_nested_type(int index); + ::google::protobuf::DescriptorProto* add_nested_type(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& nested_type() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* mutable_nested_type(); // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; - inline int enum_type_size() const; - inline void clear_enum_type(); + int enum_type_size() const; + void clear_enum_type(); static const int kEnumTypeFieldNumber = 4; - inline const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const; - inline ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index); - inline ::google::protobuf::EnumDescriptorProto* add_enum_type(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& + const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const; + ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index); + ::google::protobuf::EnumDescriptorProto* add_enum_type(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& enum_type() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* mutable_enum_type(); // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; - inline int extension_range_size() const; - inline void clear_extension_range(); + int extension_range_size() const; + void clear_extension_range(); static const int kExtensionRangeFieldNumber = 5; - inline const ::google::protobuf::DescriptorProto_ExtensionRange& extension_range(int index) const; - inline ::google::protobuf::DescriptorProto_ExtensionRange* mutable_extension_range(int index); - inline ::google::protobuf::DescriptorProto_ExtensionRange* add_extension_range(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >& + const ::google::protobuf::DescriptorProto_ExtensionRange& extension_range(int index) const; + ::google::protobuf::DescriptorProto_ExtensionRange* mutable_extension_range(int index); + ::google::protobuf::DescriptorProto_ExtensionRange* add_extension_range(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >& extension_range() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >* mutable_extension_range(); // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; - inline int oneof_decl_size() const; - inline void clear_oneof_decl(); + int oneof_decl_size() const; + void clear_oneof_decl(); static const int kOneofDeclFieldNumber = 8; - inline const ::google::protobuf::OneofDescriptorProto& oneof_decl(int index) const; - inline ::google::protobuf::OneofDescriptorProto* mutable_oneof_decl(int index); - inline ::google::protobuf::OneofDescriptorProto* add_oneof_decl(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >& + const ::google::protobuf::OneofDescriptorProto& oneof_decl(int index) const; + ::google::protobuf::OneofDescriptorProto* mutable_oneof_decl(int index); + ::google::protobuf::OneofDescriptorProto* add_oneof_decl(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >& oneof_decl() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >* mutable_oneof_decl(); // optional .google.protobuf.MessageOptions options = 7; - inline bool has_options() const; - inline void clear_options(); + bool has_options() const; + void clear_options(); static const int kOptionsFieldNumber = 7; - inline const ::google::protobuf::MessageOptions& options() const; - inline ::google::protobuf::MessageOptions* mutable_options(); - inline ::google::protobuf::MessageOptions* release_options(); - inline void set_allocated_options(::google::protobuf::MessageOptions* options); + const ::google::protobuf::MessageOptions& options() const; + ::google::protobuf::MessageOptions* mutable_options(); + ::google::protobuf::MessageOptions* release_options(); + void set_allocated_options(::google::protobuf::MessageOptions* options); // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto) private: @@ -907,89 +907,89 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa // accessors ------------------------------------------------------- // optional string name = 1; - inline bool has_name() const; - inline void clear_name(); + bool has_name() const; + void clear_name(); static const int kNameFieldNumber = 1; - inline const ::std::string& name() const; - inline void set_name(const ::std::string& value); - inline void set_name(const char* value); - inline void set_name(const char* value, size_t size); - inline ::std::string* mutable_name(); - inline ::std::string* release_name(); - inline void set_allocated_name(::std::string* name); + const ::std::string& name() const; + void set_name(const ::std::string& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + ::std::string* mutable_name(); + ::std::string* release_name(); + void set_allocated_name(::std::string* name); // optional int32 number = 3; - inline bool has_number() const; - inline void clear_number(); + bool has_number() const; + void clear_number(); static const int kNumberFieldNumber = 3; - inline ::google::protobuf::int32 number() const; - inline void set_number(::google::protobuf::int32 value); + ::google::protobuf::int32 number() const; + void set_number(::google::protobuf::int32 value); // optional .google.protobuf.FieldDescriptorProto.Label label = 4; - inline bool has_label() const; - inline void clear_label(); + bool has_label() const; + void clear_label(); static const int kLabelFieldNumber = 4; - inline ::google::protobuf::FieldDescriptorProto_Label label() const; - inline void set_label(::google::protobuf::FieldDescriptorProto_Label value); + ::google::protobuf::FieldDescriptorProto_Label label() const; + void set_label(::google::protobuf::FieldDescriptorProto_Label value); // optional .google.protobuf.FieldDescriptorProto.Type type = 5; - inline bool has_type() const; - inline void clear_type(); + bool has_type() const; + void clear_type(); static const int kTypeFieldNumber = 5; - inline ::google::protobuf::FieldDescriptorProto_Type type() const; - inline void set_type(::google::protobuf::FieldDescriptorProto_Type value); + ::google::protobuf::FieldDescriptorProto_Type type() const; + void set_type(::google::protobuf::FieldDescriptorProto_Type value); // optional string type_name = 6; - inline bool has_type_name() const; - inline void clear_type_name(); + bool has_type_name() const; + void clear_type_name(); static const int kTypeNameFieldNumber = 6; - inline const ::std::string& type_name() const; - inline void set_type_name(const ::std::string& value); - inline void set_type_name(const char* value); - inline void set_type_name(const char* value, size_t size); - inline ::std::string* mutable_type_name(); - inline ::std::string* release_type_name(); - inline void set_allocated_type_name(::std::string* type_name); + const ::std::string& type_name() const; + void set_type_name(const ::std::string& value); + void set_type_name(const char* value); + void set_type_name(const char* value, size_t size); + ::std::string* mutable_type_name(); + ::std::string* release_type_name(); + void set_allocated_type_name(::std::string* type_name); // optional string extendee = 2; - inline bool has_extendee() const; - inline void clear_extendee(); + bool has_extendee() const; + void clear_extendee(); static const int kExtendeeFieldNumber = 2; - inline const ::std::string& extendee() const; - inline void set_extendee(const ::std::string& value); - inline void set_extendee(const char* value); - inline void set_extendee(const char* value, size_t size); - inline ::std::string* mutable_extendee(); - inline ::std::string* release_extendee(); - inline void set_allocated_extendee(::std::string* extendee); + const ::std::string& extendee() const; + void set_extendee(const ::std::string& value); + void set_extendee(const char* value); + void set_extendee(const char* value, size_t size); + ::std::string* mutable_extendee(); + ::std::string* release_extendee(); + void set_allocated_extendee(::std::string* extendee); // optional string default_value = 7; - inline bool has_default_value() const; - inline void clear_default_value(); + bool has_default_value() const; + void clear_default_value(); static const int kDefaultValueFieldNumber = 7; - inline const ::std::string& default_value() const; - inline void set_default_value(const ::std::string& value); - inline void set_default_value(const char* value); - inline void set_default_value(const char* value, size_t size); - inline ::std::string* mutable_default_value(); - inline ::std::string* release_default_value(); - inline void set_allocated_default_value(::std::string* default_value); + const ::std::string& default_value() const; + void set_default_value(const ::std::string& value); + void set_default_value(const char* value); + void set_default_value(const char* value, size_t size); + ::std::string* mutable_default_value(); + ::std::string* release_default_value(); + void set_allocated_default_value(::std::string* default_value); // optional int32 oneof_index = 9; - inline bool has_oneof_index() const; - inline void clear_oneof_index(); + bool has_oneof_index() const; + void clear_oneof_index(); static const int kOneofIndexFieldNumber = 9; - inline ::google::protobuf::int32 oneof_index() const; - inline void set_oneof_index(::google::protobuf::int32 value); + ::google::protobuf::int32 oneof_index() const; + void set_oneof_index(::google::protobuf::int32 value); // optional .google.protobuf.FieldOptions options = 8; - inline bool has_options() const; - inline void clear_options(); + bool has_options() const; + void clear_options(); static const int kOptionsFieldNumber = 8; - inline const ::google::protobuf::FieldOptions& options() const; - inline ::google::protobuf::FieldOptions* mutable_options(); - inline ::google::protobuf::FieldOptions* release_options(); - inline void set_allocated_options(::google::protobuf::FieldOptions* options); + const ::google::protobuf::FieldOptions& options() const; + ::google::protobuf::FieldOptions* mutable_options(); + ::google::protobuf::FieldOptions* release_options(); + void set_allocated_options(::google::protobuf::FieldOptions* options); // @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto) private: @@ -1098,16 +1098,16 @@ class LIBPROTOBUF_EXPORT OneofDescriptorProto : public ::google::protobuf::Messa // accessors ------------------------------------------------------- // optional string name = 1; - inline bool has_name() const; - inline void clear_name(); + bool has_name() const; + void clear_name(); static const int kNameFieldNumber = 1; - inline const ::std::string& name() const; - inline void set_name(const ::std::string& value); - inline void set_name(const char* value); - inline void set_name(const char* value, size_t size); - inline ::std::string* mutable_name(); - inline ::std::string* release_name(); - inline void set_allocated_name(::std::string* name); + const ::std::string& name() const; + void set_name(const ::std::string& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + ::std::string* mutable_name(); + ::std::string* release_name(); + void set_allocated_name(::std::string* name); // @@protoc_insertion_point(class_scope:google.protobuf.OneofDescriptorProto) private: @@ -1192,37 +1192,37 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag // accessors ------------------------------------------------------- // optional string name = 1; - inline bool has_name() const; - inline void clear_name(); + bool has_name() const; + void clear_name(); static const int kNameFieldNumber = 1; - inline const ::std::string& name() const; - inline void set_name(const ::std::string& value); - inline void set_name(const char* value); - inline void set_name(const char* value, size_t size); - inline ::std::string* mutable_name(); - inline ::std::string* release_name(); - inline void set_allocated_name(::std::string* name); + const ::std::string& name() const; + void set_name(const ::std::string& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + ::std::string* mutable_name(); + ::std::string* release_name(); + void set_allocated_name(::std::string* name); // repeated .google.protobuf.EnumValueDescriptorProto value = 2; - inline int value_size() const; - inline void clear_value(); + int value_size() const; + void clear_value(); static const int kValueFieldNumber = 2; - inline const ::google::protobuf::EnumValueDescriptorProto& value(int index) const; - inline ::google::protobuf::EnumValueDescriptorProto* mutable_value(int index); - inline ::google::protobuf::EnumValueDescriptorProto* add_value(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >& + const ::google::protobuf::EnumValueDescriptorProto& value(int index) const; + ::google::protobuf::EnumValueDescriptorProto* mutable_value(int index); + ::google::protobuf::EnumValueDescriptorProto* add_value(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >& value() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >* mutable_value(); // optional .google.protobuf.EnumOptions options = 3; - inline bool has_options() const; - inline void clear_options(); + bool has_options() const; + void clear_options(); static const int kOptionsFieldNumber = 3; - inline const ::google::protobuf::EnumOptions& options() const; - inline ::google::protobuf::EnumOptions* mutable_options(); - inline ::google::protobuf::EnumOptions* release_options(); - inline void set_allocated_options(::google::protobuf::EnumOptions* options); + const ::google::protobuf::EnumOptions& options() const; + ::google::protobuf::EnumOptions* mutable_options(); + ::google::protobuf::EnumOptions* release_options(); + void set_allocated_options(::google::protobuf::EnumOptions* options); // @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto) private: @@ -1311,32 +1311,32 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M // accessors ------------------------------------------------------- // optional string name = 1; - inline bool has_name() const; - inline void clear_name(); + bool has_name() const; + void clear_name(); static const int kNameFieldNumber = 1; - inline const ::std::string& name() const; - inline void set_name(const ::std::string& value); - inline void set_name(const char* value); - inline void set_name(const char* value, size_t size); - inline ::std::string* mutable_name(); - inline ::std::string* release_name(); - inline void set_allocated_name(::std::string* name); + const ::std::string& name() const; + void set_name(const ::std::string& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + ::std::string* mutable_name(); + ::std::string* release_name(); + void set_allocated_name(::std::string* name); // optional int32 number = 2; - inline bool has_number() const; - inline void clear_number(); + bool has_number() const; + void clear_number(); static const int kNumberFieldNumber = 2; - inline ::google::protobuf::int32 number() const; - inline void set_number(::google::protobuf::int32 value); + ::google::protobuf::int32 number() const; + void set_number(::google::protobuf::int32 value); // optional .google.protobuf.EnumValueOptions options = 3; - inline bool has_options() const; - inline void clear_options(); + bool has_options() const; + void clear_options(); static const int kOptionsFieldNumber = 3; - inline const ::google::protobuf::EnumValueOptions& options() const; - inline ::google::protobuf::EnumValueOptions* mutable_options(); - inline ::google::protobuf::EnumValueOptions* release_options(); - inline void set_allocated_options(::google::protobuf::EnumValueOptions* options); + const ::google::protobuf::EnumValueOptions& options() const; + ::google::protobuf::EnumValueOptions* mutable_options(); + ::google::protobuf::EnumValueOptions* release_options(); + void set_allocated_options(::google::protobuf::EnumValueOptions* options); // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto) private: @@ -1427,37 +1427,37 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes // accessors ------------------------------------------------------- // optional string name = 1; - inline bool has_name() const; - inline void clear_name(); + bool has_name() const; + void clear_name(); static const int kNameFieldNumber = 1; - inline const ::std::string& name() const; - inline void set_name(const ::std::string& value); - inline void set_name(const char* value); - inline void set_name(const char* value, size_t size); - inline ::std::string* mutable_name(); - inline ::std::string* release_name(); - inline void set_allocated_name(::std::string* name); + const ::std::string& name() const; + void set_name(const ::std::string& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + ::std::string* mutable_name(); + ::std::string* release_name(); + void set_allocated_name(::std::string* name); // repeated .google.protobuf.MethodDescriptorProto method = 2; - inline int method_size() const; - inline void clear_method(); + int method_size() const; + void clear_method(); static const int kMethodFieldNumber = 2; - inline const ::google::protobuf::MethodDescriptorProto& method(int index) const; - inline ::google::protobuf::MethodDescriptorProto* mutable_method(int index); - inline ::google::protobuf::MethodDescriptorProto* add_method(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >& + const ::google::protobuf::MethodDescriptorProto& method(int index) const; + ::google::protobuf::MethodDescriptorProto* mutable_method(int index); + ::google::protobuf::MethodDescriptorProto* add_method(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >& method() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >* mutable_method(); // optional .google.protobuf.ServiceOptions options = 3; - inline bool has_options() const; - inline void clear_options(); + bool has_options() const; + void clear_options(); static const int kOptionsFieldNumber = 3; - inline const ::google::protobuf::ServiceOptions& options() const; - inline ::google::protobuf::ServiceOptions* mutable_options(); - inline ::google::protobuf::ServiceOptions* release_options(); - inline void set_allocated_options(::google::protobuf::ServiceOptions* options); + const ::google::protobuf::ServiceOptions& options() const; + ::google::protobuf::ServiceOptions* mutable_options(); + ::google::protobuf::ServiceOptions* release_options(); + void set_allocated_options(::google::protobuf::ServiceOptions* options); // @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto) private: @@ -1546,63 +1546,63 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess // accessors ------------------------------------------------------- // optional string name = 1; - inline bool has_name() const; - inline void clear_name(); + bool has_name() const; + void clear_name(); static const int kNameFieldNumber = 1; - inline const ::std::string& name() const; - inline void set_name(const ::std::string& value); - inline void set_name(const char* value); - inline void set_name(const char* value, size_t size); - inline ::std::string* mutable_name(); - inline ::std::string* release_name(); - inline void set_allocated_name(::std::string* name); + const ::std::string& name() const; + void set_name(const ::std::string& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + ::std::string* mutable_name(); + ::std::string* release_name(); + void set_allocated_name(::std::string* name); // optional string input_type = 2; - inline bool has_input_type() const; - inline void clear_input_type(); + bool has_input_type() const; + void clear_input_type(); static const int kInputTypeFieldNumber = 2; - inline const ::std::string& input_type() const; - inline void set_input_type(const ::std::string& value); - inline void set_input_type(const char* value); - inline void set_input_type(const char* value, size_t size); - inline ::std::string* mutable_input_type(); - inline ::std::string* release_input_type(); - inline void set_allocated_input_type(::std::string* input_type); + const ::std::string& input_type() const; + void set_input_type(const ::std::string& value); + void set_input_type(const char* value); + void set_input_type(const char* value, size_t size); + ::std::string* mutable_input_type(); + ::std::string* release_input_type(); + void set_allocated_input_type(::std::string* input_type); // optional string output_type = 3; - inline bool has_output_type() const; - inline void clear_output_type(); + bool has_output_type() const; + void clear_output_type(); static const int kOutputTypeFieldNumber = 3; - inline const ::std::string& output_type() const; - inline void set_output_type(const ::std::string& value); - inline void set_output_type(const char* value); - inline void set_output_type(const char* value, size_t size); - inline ::std::string* mutable_output_type(); - inline ::std::string* release_output_type(); - inline void set_allocated_output_type(::std::string* output_type); + const ::std::string& output_type() const; + void set_output_type(const ::std::string& value); + void set_output_type(const char* value); + void set_output_type(const char* value, size_t size); + ::std::string* mutable_output_type(); + ::std::string* release_output_type(); + void set_allocated_output_type(::std::string* output_type); // optional .google.protobuf.MethodOptions options = 4; - inline bool has_options() const; - inline void clear_options(); + bool has_options() const; + void clear_options(); static const int kOptionsFieldNumber = 4; - inline const ::google::protobuf::MethodOptions& options() const; - inline ::google::protobuf::MethodOptions* mutable_options(); - inline ::google::protobuf::MethodOptions* release_options(); - inline void set_allocated_options(::google::protobuf::MethodOptions* options); + const ::google::protobuf::MethodOptions& options() const; + ::google::protobuf::MethodOptions* mutable_options(); + ::google::protobuf::MethodOptions* release_options(); + void set_allocated_options(::google::protobuf::MethodOptions* options); // optional bool client_streaming = 5 [default = false]; - inline bool has_client_streaming() const; - inline void clear_client_streaming(); + bool has_client_streaming() const; + void clear_client_streaming(); static const int kClientStreamingFieldNumber = 5; - inline bool client_streaming() const; - inline void set_client_streaming(bool value); + bool client_streaming() const; + void set_client_streaming(bool value); // optional bool server_streaming = 6 [default = false]; - inline bool has_server_streaming() const; - inline void clear_server_streaming(); + bool has_server_streaming() const; + void clear_server_streaming(); static const int kServerStreamingFieldNumber = 6; - inline bool server_streaming() const; - inline void set_server_streaming(bool value); + bool server_streaming() const; + void set_server_streaming(bool value); // @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto) private: @@ -1727,114 +1727,126 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // optional string java_package = 1; - inline bool has_java_package() const; - inline void clear_java_package(); + bool has_java_package() const; + void clear_java_package(); static const int kJavaPackageFieldNumber = 1; - inline const ::std::string& java_package() const; - inline void set_java_package(const ::std::string& value); - inline void set_java_package(const char* value); - inline void set_java_package(const char* value, size_t size); - inline ::std::string* mutable_java_package(); - inline ::std::string* release_java_package(); - inline void set_allocated_java_package(::std::string* java_package); + const ::std::string& java_package() const; + void set_java_package(const ::std::string& value); + void set_java_package(const char* value); + void set_java_package(const char* value, size_t size); + ::std::string* mutable_java_package(); + ::std::string* release_java_package(); + void set_allocated_java_package(::std::string* java_package); // optional string java_outer_classname = 8; - inline bool has_java_outer_classname() const; - inline void clear_java_outer_classname(); + bool has_java_outer_classname() const; + void clear_java_outer_classname(); static const int kJavaOuterClassnameFieldNumber = 8; - inline const ::std::string& java_outer_classname() const; - inline void set_java_outer_classname(const ::std::string& value); - inline void set_java_outer_classname(const char* value); - inline void set_java_outer_classname(const char* value, size_t size); - inline ::std::string* mutable_java_outer_classname(); - inline ::std::string* release_java_outer_classname(); - inline void set_allocated_java_outer_classname(::std::string* java_outer_classname); + const ::std::string& java_outer_classname() const; + void set_java_outer_classname(const ::std::string& value); + void set_java_outer_classname(const char* value); + void set_java_outer_classname(const char* value, size_t size); + ::std::string* mutable_java_outer_classname(); + ::std::string* release_java_outer_classname(); + void set_allocated_java_outer_classname(::std::string* java_outer_classname); // optional bool java_multiple_files = 10 [default = false]; - inline bool has_java_multiple_files() const; - inline void clear_java_multiple_files(); + bool has_java_multiple_files() const; + void clear_java_multiple_files(); static const int kJavaMultipleFilesFieldNumber = 10; - inline bool java_multiple_files() const; - inline void set_java_multiple_files(bool value); + bool java_multiple_files() const; + void set_java_multiple_files(bool value); // optional bool java_generate_equals_and_hash = 20 [default = false]; - inline bool has_java_generate_equals_and_hash() const; - inline void clear_java_generate_equals_and_hash(); + bool has_java_generate_equals_and_hash() const; + void clear_java_generate_equals_and_hash(); static const int kJavaGenerateEqualsAndHashFieldNumber = 20; - inline bool java_generate_equals_and_hash() const; - inline void set_java_generate_equals_and_hash(bool value); + bool java_generate_equals_and_hash() const; + void set_java_generate_equals_and_hash(bool value); // optional bool java_string_check_utf8 = 27 [default = false]; - inline bool has_java_string_check_utf8() const; - inline void clear_java_string_check_utf8(); + bool has_java_string_check_utf8() const; + void clear_java_string_check_utf8(); static const int kJavaStringCheckUtf8FieldNumber = 27; - inline bool java_string_check_utf8() const; - inline void set_java_string_check_utf8(bool value); + bool java_string_check_utf8() const; + void set_java_string_check_utf8(bool value); // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; - inline bool has_optimize_for() const; - inline void clear_optimize_for(); + bool has_optimize_for() const; + void clear_optimize_for(); static const int kOptimizeForFieldNumber = 9; - inline ::google::protobuf::FileOptions_OptimizeMode optimize_for() const; - inline void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value); + ::google::protobuf::FileOptions_OptimizeMode optimize_for() const; + void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value); // optional string go_package = 11; - inline bool has_go_package() const; - inline void clear_go_package(); + bool has_go_package() const; + void clear_go_package(); static const int kGoPackageFieldNumber = 11; - inline const ::std::string& go_package() const; - inline void set_go_package(const ::std::string& value); - inline void set_go_package(const char* value); - inline void set_go_package(const char* value, size_t size); - inline ::std::string* mutable_go_package(); - inline ::std::string* release_go_package(); - inline void set_allocated_go_package(::std::string* go_package); + const ::std::string& go_package() const; + void set_go_package(const ::std::string& value); + void set_go_package(const char* value); + void set_go_package(const char* value, size_t size); + ::std::string* mutable_go_package(); + ::std::string* release_go_package(); + void set_allocated_go_package(::std::string* go_package); // optional bool cc_generic_services = 16 [default = false]; - inline bool has_cc_generic_services() const; - inline void clear_cc_generic_services(); + bool has_cc_generic_services() const; + void clear_cc_generic_services(); static const int kCcGenericServicesFieldNumber = 16; - inline bool cc_generic_services() const; - inline void set_cc_generic_services(bool value); + bool cc_generic_services() const; + void set_cc_generic_services(bool value); // optional bool java_generic_services = 17 [default = false]; - inline bool has_java_generic_services() const; - inline void clear_java_generic_services(); + bool has_java_generic_services() const; + void clear_java_generic_services(); static const int kJavaGenericServicesFieldNumber = 17; - inline bool java_generic_services() const; - inline void set_java_generic_services(bool value); + bool java_generic_services() const; + void set_java_generic_services(bool value); // optional bool py_generic_services = 18 [default = false]; - inline bool has_py_generic_services() const; - inline void clear_py_generic_services(); + bool has_py_generic_services() const; + void clear_py_generic_services(); static const int kPyGenericServicesFieldNumber = 18; - inline bool py_generic_services() const; - inline void set_py_generic_services(bool value); + bool py_generic_services() const; + void set_py_generic_services(bool value); // optional bool deprecated = 23 [default = false]; - inline bool has_deprecated() const; - inline void clear_deprecated(); + bool has_deprecated() const; + void clear_deprecated(); static const int kDeprecatedFieldNumber = 23; - inline bool deprecated() const; - inline void set_deprecated(bool value); + bool deprecated() const; + void set_deprecated(bool value); // optional bool cc_enable_arenas = 31 [default = false]; - inline bool has_cc_enable_arenas() const; - inline void clear_cc_enable_arenas(); + bool has_cc_enable_arenas() const; + void clear_cc_enable_arenas(); static const int kCcEnableArenasFieldNumber = 31; - inline bool cc_enable_arenas() const; - inline void set_cc_enable_arenas(bool value); + bool cc_enable_arenas() const; + void set_cc_enable_arenas(bool value); + + // optional string objc_class_prefix = 36; + bool has_objc_class_prefix() const; + void clear_objc_class_prefix(); + static const int kObjcClassPrefixFieldNumber = 36; + const ::std::string& objc_class_prefix() const; + void set_objc_class_prefix(const ::std::string& value); + void set_objc_class_prefix(const char* value); + void set_objc_class_prefix(const char* value, size_t size); + ::std::string* mutable_objc_class_prefix(); + ::std::string* release_objc_class_prefix(); + void set_allocated_objc_class_prefix(::std::string* objc_class_prefix); // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - inline int uninterpreted_option_size() const; - inline void clear_uninterpreted_option(); + int uninterpreted_option_size() const; + void clear_uninterpreted_option(); static const int kUninterpretedOptionFieldNumber = 999; - inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions) @@ -1864,6 +1876,8 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { inline void clear_has_deprecated(); inline void set_has_cc_enable_arenas(); inline void clear_has_cc_enable_arenas(); + inline void set_has_objc_class_prefix(); + inline void clear_has_objc_class_prefix(); ::google::protobuf::internal::ExtensionSet _extensions_; @@ -1878,6 +1892,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { bool cc_generic_services_; int optimize_for_; ::google::protobuf::internal::ArenaStringPtr go_package_; + ::google::protobuf::internal::ArenaStringPtr objc_class_prefix_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; bool java_generic_services_; bool py_generic_services_; @@ -1957,43 +1972,43 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // optional bool message_set_wire_format = 1 [default = false]; - inline bool has_message_set_wire_format() const; - inline void clear_message_set_wire_format(); + bool has_message_set_wire_format() const; + void clear_message_set_wire_format(); static const int kMessageSetWireFormatFieldNumber = 1; - inline bool message_set_wire_format() const; - inline void set_message_set_wire_format(bool value); + bool message_set_wire_format() const; + void set_message_set_wire_format(bool value); // optional bool no_standard_descriptor_accessor = 2 [default = false]; - inline bool has_no_standard_descriptor_accessor() const; - inline void clear_no_standard_descriptor_accessor(); + bool has_no_standard_descriptor_accessor() const; + void clear_no_standard_descriptor_accessor(); static const int kNoStandardDescriptorAccessorFieldNumber = 2; - inline bool no_standard_descriptor_accessor() const; - inline void set_no_standard_descriptor_accessor(bool value); + bool no_standard_descriptor_accessor() const; + void set_no_standard_descriptor_accessor(bool value); // optional bool deprecated = 3 [default = false]; - inline bool has_deprecated() const; - inline void clear_deprecated(); + bool has_deprecated() const; + void clear_deprecated(); static const int kDeprecatedFieldNumber = 3; - inline bool deprecated() const; - inline void set_deprecated(bool value); + bool deprecated() const; + void set_deprecated(bool value); // optional bool map_entry = 7; - inline bool has_map_entry() const; - inline void clear_map_entry(); + bool has_map_entry() const; + void clear_map_entry(); static const int kMapEntryFieldNumber = 7; - inline bool map_entry() const; - inline void set_map_entry(bool value); + bool map_entry() const; + void set_map_entry(bool value); // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - inline int uninterpreted_option_size() const; - inline void clear_uninterpreted_option(); + int uninterpreted_option_size() const; + void clear_uninterpreted_option(); static const int kUninterpretedOptionFieldNumber = 999; - inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions) @@ -2117,50 +2132,50 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; - inline bool has_ctype() const; - inline void clear_ctype(); + bool has_ctype() const; + void clear_ctype(); static const int kCtypeFieldNumber = 1; - inline ::google::protobuf::FieldOptions_CType ctype() const; - inline void set_ctype(::google::protobuf::FieldOptions_CType value); + ::google::protobuf::FieldOptions_CType ctype() const; + void set_ctype(::google::protobuf::FieldOptions_CType value); // optional bool packed = 2; - inline bool has_packed() const; - inline void clear_packed(); + bool has_packed() const; + void clear_packed(); static const int kPackedFieldNumber = 2; - inline bool packed() const; - inline void set_packed(bool value); + bool packed() const; + void set_packed(bool value); // optional bool lazy = 5 [default = false]; - inline bool has_lazy() const; - inline void clear_lazy(); + bool has_lazy() const; + void clear_lazy(); static const int kLazyFieldNumber = 5; - inline bool lazy() const; - inline void set_lazy(bool value); + bool lazy() const; + void set_lazy(bool value); // optional bool deprecated = 3 [default = false]; - inline bool has_deprecated() const; - inline void clear_deprecated(); + bool has_deprecated() const; + void clear_deprecated(); static const int kDeprecatedFieldNumber = 3; - inline bool deprecated() const; - inline void set_deprecated(bool value); + bool deprecated() const; + void set_deprecated(bool value); // optional bool weak = 10 [default = false]; - inline bool has_weak() const; - inline void clear_weak(); + bool has_weak() const; + void clear_weak(); static const int kWeakFieldNumber = 10; - inline bool weak() const; - inline void set_weak(bool value); + bool weak() const; + void set_weak(bool value); // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - inline int uninterpreted_option_size() const; - inline void clear_uninterpreted_option(); + int uninterpreted_option_size() const; + void clear_uninterpreted_option(); static const int kUninterpretedOptionFieldNumber = 999; - inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions) @@ -2262,29 +2277,29 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // optional bool allow_alias = 2; - inline bool has_allow_alias() const; - inline void clear_allow_alias(); + bool has_allow_alias() const; + void clear_allow_alias(); static const int kAllowAliasFieldNumber = 2; - inline bool allow_alias() const; - inline void set_allow_alias(bool value); + bool allow_alias() const; + void set_allow_alias(bool value); // optional bool deprecated = 3 [default = false]; - inline bool has_deprecated() const; - inline void clear_deprecated(); + bool has_deprecated() const; + void clear_deprecated(); static const int kDeprecatedFieldNumber = 3; - inline bool deprecated() const; - inline void set_deprecated(bool value); + bool deprecated() const; + void set_deprecated(bool value); // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - inline int uninterpreted_option_size() const; - inline void clear_uninterpreted_option(); + int uninterpreted_option_size() const; + void clear_uninterpreted_option(); static const int kUninterpretedOptionFieldNumber = 999; - inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions) @@ -2377,22 +2392,22 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // optional bool deprecated = 1 [default = false]; - inline bool has_deprecated() const; - inline void clear_deprecated(); + bool has_deprecated() const; + void clear_deprecated(); static const int kDeprecatedFieldNumber = 1; - inline bool deprecated() const; - inline void set_deprecated(bool value); + bool deprecated() const; + void set_deprecated(bool value); // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - inline int uninterpreted_option_size() const; - inline void clear_uninterpreted_option(); + int uninterpreted_option_size() const; + void clear_uninterpreted_option(); static const int kUninterpretedOptionFieldNumber = 999; - inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions) @@ -2482,22 +2497,22 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // optional bool deprecated = 33 [default = false]; - inline bool has_deprecated() const; - inline void clear_deprecated(); + bool has_deprecated() const; + void clear_deprecated(); static const int kDeprecatedFieldNumber = 33; - inline bool deprecated() const; - inline void set_deprecated(bool value); + bool deprecated() const; + void set_deprecated(bool value); // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - inline int uninterpreted_option_size() const; - inline void clear_uninterpreted_option(); + int uninterpreted_option_size() const; + void clear_uninterpreted_option(); static const int kUninterpretedOptionFieldNumber = 999; - inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions) @@ -2587,22 +2602,22 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // optional bool deprecated = 33 [default = false]; - inline bool has_deprecated() const; - inline void clear_deprecated(); + bool has_deprecated() const; + void clear_deprecated(); static const int kDeprecatedFieldNumber = 33; - inline bool deprecated() const; - inline void set_deprecated(bool value); + bool deprecated() const; + void set_deprecated(bool value); // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - inline int uninterpreted_option_size() const; - inline void clear_uninterpreted_option(); + int uninterpreted_option_size() const; + void clear_uninterpreted_option(); static const int kUninterpretedOptionFieldNumber = 999; - inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions) @@ -2692,23 +2707,23 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu // accessors ------------------------------------------------------- // required string name_part = 1; - inline bool has_name_part() const; - inline void clear_name_part(); + bool has_name_part() const; + void clear_name_part(); static const int kNamePartFieldNumber = 1; - inline const ::std::string& name_part() const; - inline void set_name_part(const ::std::string& value); - inline void set_name_part(const char* value); - inline void set_name_part(const char* value, size_t size); - inline ::std::string* mutable_name_part(); - inline ::std::string* release_name_part(); - inline void set_allocated_name_part(::std::string* name_part); + const ::std::string& name_part() const; + void set_name_part(const ::std::string& value); + void set_name_part(const char* value); + void set_name_part(const char* value, size_t size); + ::std::string* mutable_name_part(); + ::std::string* release_name_part(); + void set_allocated_name_part(::std::string* name_part); // required bool is_extension = 2; - inline bool has_is_extension() const; - inline void clear_is_extension(); + bool has_is_extension() const; + void clear_is_extension(); static const int kIsExtensionFieldNumber = 2; - inline bool is_extension() const; - inline void set_is_extension(bool value); + bool is_extension() const; + void set_is_extension(bool value); // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart) private: @@ -2801,73 +2816,73 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag // accessors ------------------------------------------------------- // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; - inline int name_size() const; - inline void clear_name(); + int name_size() const; + void clear_name(); static const int kNameFieldNumber = 2; - inline const ::google::protobuf::UninterpretedOption_NamePart& name(int index) const; - inline ::google::protobuf::UninterpretedOption_NamePart* mutable_name(int index); - inline ::google::protobuf::UninterpretedOption_NamePart* add_name(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >& + const ::google::protobuf::UninterpretedOption_NamePart& name(int index) const; + ::google::protobuf::UninterpretedOption_NamePart* mutable_name(int index); + ::google::protobuf::UninterpretedOption_NamePart* add_name(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >& name() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >* mutable_name(); // optional string identifier_value = 3; - inline bool has_identifier_value() const; - inline void clear_identifier_value(); + bool has_identifier_value() const; + void clear_identifier_value(); static const int kIdentifierValueFieldNumber = 3; - inline const ::std::string& identifier_value() const; - inline void set_identifier_value(const ::std::string& value); - inline void set_identifier_value(const char* value); - inline void set_identifier_value(const char* value, size_t size); - inline ::std::string* mutable_identifier_value(); - inline ::std::string* release_identifier_value(); - inline void set_allocated_identifier_value(::std::string* identifier_value); + const ::std::string& identifier_value() const; + void set_identifier_value(const ::std::string& value); + void set_identifier_value(const char* value); + void set_identifier_value(const char* value, size_t size); + ::std::string* mutable_identifier_value(); + ::std::string* release_identifier_value(); + void set_allocated_identifier_value(::std::string* identifier_value); // optional uint64 positive_int_value = 4; - inline bool has_positive_int_value() const; - inline void clear_positive_int_value(); + bool has_positive_int_value() const; + void clear_positive_int_value(); static const int kPositiveIntValueFieldNumber = 4; - inline ::google::protobuf::uint64 positive_int_value() const; - inline void set_positive_int_value(::google::protobuf::uint64 value); + ::google::protobuf::uint64 positive_int_value() const; + void set_positive_int_value(::google::protobuf::uint64 value); // optional int64 negative_int_value = 5; - inline bool has_negative_int_value() const; - inline void clear_negative_int_value(); + bool has_negative_int_value() const; + void clear_negative_int_value(); static const int kNegativeIntValueFieldNumber = 5; - inline ::google::protobuf::int64 negative_int_value() const; - inline void set_negative_int_value(::google::protobuf::int64 value); + ::google::protobuf::int64 negative_int_value() const; + void set_negative_int_value(::google::protobuf::int64 value); // optional double double_value = 6; - inline bool has_double_value() const; - inline void clear_double_value(); + bool has_double_value() const; + void clear_double_value(); static const int kDoubleValueFieldNumber = 6; - inline double double_value() const; - inline void set_double_value(double value); + double double_value() const; + void set_double_value(double value); // optional bytes string_value = 7; - inline bool has_string_value() const; - inline void clear_string_value(); + bool has_string_value() const; + void clear_string_value(); static const int kStringValueFieldNumber = 7; - inline const ::std::string& string_value() const; - inline void set_string_value(const ::std::string& value); - inline void set_string_value(const char* value); - inline void set_string_value(const void* value, size_t size); - inline ::std::string* mutable_string_value(); - inline ::std::string* release_string_value(); - inline void set_allocated_string_value(::std::string* string_value); + const ::std::string& string_value() const; + void set_string_value(const ::std::string& value); + void set_string_value(const char* value); + void set_string_value(const void* value, size_t size); + ::std::string* mutable_string_value(); + ::std::string* release_string_value(); + void set_allocated_string_value(::std::string* string_value); // optional string aggregate_value = 8; - inline bool has_aggregate_value() const; - inline void clear_aggregate_value(); + bool has_aggregate_value() const; + void clear_aggregate_value(); static const int kAggregateValueFieldNumber = 8; - inline const ::std::string& aggregate_value() const; - inline void set_aggregate_value(const ::std::string& value); - inline void set_aggregate_value(const char* value); - inline void set_aggregate_value(const char* value, size_t size); - inline ::std::string* mutable_aggregate_value(); - inline ::std::string* release_aggregate_value(); - inline void set_allocated_aggregate_value(::std::string* aggregate_value); + const ::std::string& aggregate_value() const; + void set_aggregate_value(const ::std::string& value); + void set_aggregate_value(const char* value); + void set_aggregate_value(const char* value, size_t size); + ::std::string* mutable_aggregate_value(); + ::std::string* release_aggregate_value(); + void set_allocated_aggregate_value(::std::string* aggregate_value); // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption) private: @@ -2968,52 +2983,68 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Me // accessors ------------------------------------------------------- // repeated int32 path = 1 [packed = true]; - inline int path_size() const; - inline void clear_path(); + int path_size() const; + void clear_path(); static const int kPathFieldNumber = 1; - inline ::google::protobuf::int32 path(int index) const; - inline void set_path(int index, ::google::protobuf::int32 value); - inline void add_path(::google::protobuf::int32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + ::google::protobuf::int32 path(int index) const; + void set_path(int index, ::google::protobuf::int32 value); + void add_path(::google::protobuf::int32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& path() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* mutable_path(); // repeated int32 span = 2 [packed = true]; - inline int span_size() const; - inline void clear_span(); + int span_size() const; + void clear_span(); static const int kSpanFieldNumber = 2; - inline ::google::protobuf::int32 span(int index) const; - inline void set_span(int index, ::google::protobuf::int32 value); - inline void add_span(::google::protobuf::int32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + ::google::protobuf::int32 span(int index) const; + void set_span(int index, ::google::protobuf::int32 value); + void add_span(::google::protobuf::int32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& span() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* mutable_span(); // optional string leading_comments = 3; - inline bool has_leading_comments() const; - inline void clear_leading_comments(); + bool has_leading_comments() const; + void clear_leading_comments(); static const int kLeadingCommentsFieldNumber = 3; - inline const ::std::string& leading_comments() const; - inline void set_leading_comments(const ::std::string& value); - inline void set_leading_comments(const char* value); - inline void set_leading_comments(const char* value, size_t size); - inline ::std::string* mutable_leading_comments(); - inline ::std::string* release_leading_comments(); - inline void set_allocated_leading_comments(::std::string* leading_comments); + const ::std::string& leading_comments() const; + void set_leading_comments(const ::std::string& value); + void set_leading_comments(const char* value); + void set_leading_comments(const char* value, size_t size); + ::std::string* mutable_leading_comments(); + ::std::string* release_leading_comments(); + void set_allocated_leading_comments(::std::string* leading_comments); // optional string trailing_comments = 4; - inline bool has_trailing_comments() const; - inline void clear_trailing_comments(); + bool has_trailing_comments() const; + void clear_trailing_comments(); static const int kTrailingCommentsFieldNumber = 4; - inline const ::std::string& trailing_comments() const; - inline void set_trailing_comments(const ::std::string& value); - inline void set_trailing_comments(const char* value); - inline void set_trailing_comments(const char* value, size_t size); - inline ::std::string* mutable_trailing_comments(); - inline ::std::string* release_trailing_comments(); - inline void set_allocated_trailing_comments(::std::string* trailing_comments); + const ::std::string& trailing_comments() const; + void set_trailing_comments(const ::std::string& value); + void set_trailing_comments(const char* value); + void set_trailing_comments(const char* value, size_t size); + ::std::string* mutable_trailing_comments(); + ::std::string* release_trailing_comments(); + void set_allocated_trailing_comments(::std::string* trailing_comments); + + // repeated string leading_detached_comments = 6; + int leading_detached_comments_size() const; + void clear_leading_detached_comments(); + static const int kLeadingDetachedCommentsFieldNumber = 6; + const ::std::string& leading_detached_comments(int index) const; + ::std::string* mutable_leading_detached_comments(int index); + void set_leading_detached_comments(int index, const ::std::string& value); + void set_leading_detached_comments(int index, const char* value); + void set_leading_detached_comments(int index, const char* value, size_t size); + ::std::string* add_leading_detached_comments(); + void add_leading_detached_comments(const ::std::string& value); + void add_leading_detached_comments(const char* value); + void add_leading_detached_comments(const char* value, size_t size); + const ::google::protobuf::RepeatedPtrField< ::std::string>& leading_detached_comments() const; + ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_leading_detached_comments(); // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location) private: @@ -3031,6 +3062,7 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Me mutable int _span_cached_byte_size_; ::google::protobuf::internal::ArenaStringPtr leading_comments_; ::google::protobuf::internal::ArenaStringPtr trailing_comments_; + ::google::protobuf::RepeatedPtrField< ::std::string> leading_detached_comments_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -3107,15 +3139,15 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // repeated .google.protobuf.SourceCodeInfo.Location location = 1; - inline int location_size() const; - inline void clear_location(); + int location_size() const; + void clear_location(); static const int kLocationFieldNumber = 1; - inline const ::google::protobuf::SourceCodeInfo_Location& location(int index) const; - inline ::google::protobuf::SourceCodeInfo_Location* mutable_location(int index); - inline ::google::protobuf::SourceCodeInfo_Location* add_location(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& + const ::google::protobuf::SourceCodeInfo_Location& location(int index) const; + ::google::protobuf::SourceCodeInfo_Location* mutable_location(int index); + ::google::protobuf::SourceCodeInfo_Location* add_location(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& location() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >* mutable_location(); // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo) @@ -3137,6 +3169,7 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message { // =================================================================== +#if !PROTOBUF_INLINE_NOT_IN_HEADERS // FileDescriptorSet // repeated .google.protobuf.FileDescriptorProto file = 1; @@ -5416,6 +5449,59 @@ inline void FileOptions::set_cc_enable_arenas(bool value) { // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_enable_arenas) } +// optional string objc_class_prefix = 36; +inline bool FileOptions::has_objc_class_prefix() const { + return (_has_bits_[0] & 0x00001000u) != 0; +} +inline void FileOptions::set_has_objc_class_prefix() { + _has_bits_[0] |= 0x00001000u; +} +inline void FileOptions::clear_has_objc_class_prefix() { + _has_bits_[0] &= ~0x00001000u; +} +inline void FileOptions::clear_objc_class_prefix() { + objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_objc_class_prefix(); +} +inline const ::std::string& FileOptions::objc_class_prefix() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.objc_class_prefix) + return objc_class_prefix_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void FileOptions::set_objc_class_prefix(const ::std::string& value) { + set_has_objc_class_prefix(); + objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.objc_class_prefix) +} +inline void FileOptions::set_objc_class_prefix(const char* value) { + set_has_objc_class_prefix(); + objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.objc_class_prefix) +} +inline void FileOptions::set_objc_class_prefix(const char* value, size_t size) { + set_has_objc_class_prefix(); + objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast<const char*>(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.objc_class_prefix) +} +inline ::std::string* FileOptions::mutable_objc_class_prefix() { + set_has_objc_class_prefix(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.objc_class_prefix) + return objc_class_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline ::std::string* FileOptions::release_objc_class_prefix() { + clear_has_objc_class_prefix(); + return objc_class_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void FileOptions::set_allocated_objc_class_prefix(::std::string* objc_class_prefix) { + if (objc_class_prefix != NULL) { + set_has_objc_class_prefix(); + } else { + clear_has_objc_class_prefix(); + } + objc_class_prefix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), objc_class_prefix); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.objc_class_prefix) +} + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int FileOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); @@ -6503,6 +6589,60 @@ inline void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::stri // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments) } +// repeated string leading_detached_comments = 6; +inline int SourceCodeInfo_Location::leading_detached_comments_size() const { + return leading_detached_comments_.size(); +} +inline void SourceCodeInfo_Location::clear_leading_detached_comments() { + leading_detached_comments_.Clear(); +} +inline const ::std::string& SourceCodeInfo_Location::leading_detached_comments(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return leading_detached_comments_.Get(index); +} +inline ::std::string* SourceCodeInfo_Location::mutable_leading_detached_comments(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return leading_detached_comments_.Mutable(index); +} +inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const ::std::string& value) { + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + leading_detached_comments_.Mutable(index)->assign(value); +} +inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value) { + leading_detached_comments_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} +inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value, size_t size) { + leading_detached_comments_.Mutable(index)->assign( + reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} +inline ::std::string* SourceCodeInfo_Location::add_leading_detached_comments() { + return leading_detached_comments_.Add(); +} +inline void SourceCodeInfo_Location::add_leading_detached_comments(const ::std::string& value) { + leading_detached_comments_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} +inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value) { + leading_detached_comments_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} +inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value, size_t size) { + leading_detached_comments_.Add()->assign(reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} +inline const ::google::protobuf::RepeatedPtrField< ::std::string>& +SourceCodeInfo_Location::leading_detached_comments() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return leading_detached_comments_; +} +inline ::google::protobuf::RepeatedPtrField< ::std::string>* +SourceCodeInfo_Location::mutable_leading_detached_comments() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return &leading_detached_comments_; +} + // ------------------------------------------------------------------- // SourceCodeInfo @@ -6537,6 +6677,7 @@ SourceCodeInfo::mutable_location() { return &location_; } +#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index e17c0cc8..de242690 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -42,6 +42,7 @@ syntax = "proto2"; package google.protobuf; option java_package = "com.google.protobuf"; option java_outer_classname = "DescriptorProtos"; +option objc_class_prefix = "GPB"; // descriptor.proto must be optimized for speed because reflection-based // algorithms don't work during bootstrapping. @@ -172,9 +173,7 @@ message FieldDescriptorProto { optional string default_value = 7; // If set, gives the index of a oneof in the containing type's oneof_decl - // list. This field is a member of that oneof. Extensions of a oneof should - // not set this since the oneof to which they belong will be inferred based - // on the extension range containing the extension's field number. + // list. This field is a member of that oneof. optional int32 oneof_index = 9; optional FieldOptions options = 8; @@ -344,12 +343,15 @@ message FileOptions { // least, this is a formalization for deprecating files. optional bool deprecated = 23 [default=false]; - // Enables the use of arenas for the proto messages in this file. This applies // only to generated classes for C++. optional bool cc_enable_arenas = 31 [default=false]; + // Sets the objective c class prefix which is prepended to all objective c + // generated classes from this .proto. There is no default. + optional string objc_class_prefix = 36; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -681,6 +683,11 @@ message SourceCodeInfo { // A series of line comments appearing on consecutive lines, with no other // tokens appearing on those lines, will be treated as a single comment. // + // leading_detached_comments will keep paragraphs of comments that appear + // before (but not connected to) the current element. Each paragraph, + // separated by empty lines, will be one comment element in the repeated + // field. + // // Only the comment content is provided; comment markers (e.g. //) are // stripped out. For block comments, leading whitespace and an asterisk // will be stripped from the beginning of each line other than the first. @@ -701,6 +708,12 @@ message SourceCodeInfo { // // Another line attached to qux. // optional double qux = 4; // + // // Detached comment for corge. This is not leading or trailing comments + // // to qux or corge because there are blank lines separating it from + // // both. + // + // // Detached comment for corge paragraph 2. + // // optional string corge = 5; // /* Block comment attached // * to corge. Leading asterisks @@ -708,7 +721,10 @@ message SourceCodeInfo { // /* Block comment attached to // * grault. */ // optional int32 grault = 6; + // + // // ignored detached comments. optional string leading_comments = 3; optional string trailing_comments = 4; + repeated string leading_detached_comments = 6; } } diff --git a/src/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc index d024eab1..2117c020 100644 --- a/src/google/protobuf/descriptor_database.cc +++ b/src/google/protobuf/descriptor_database.cc @@ -153,10 +153,10 @@ bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddExtension( if (!field.extendee().empty() && field.extendee()[0] == '.') { // The extension is fully-qualified. We can use it as a lookup key in // the by_symbol_ table. - if (!InsertIfNotPresent(&by_extension_, - make_pair(field.extendee().substr(1), - field.number()), - value)) { + if (!InsertIfNotPresent( + &by_extension_, + std::make_pair(field.extendee().substr(1), field.number()), + value)) { GOOGLE_LOG(ERROR) << "Extension conflicts with extension already in database: " "extend " << field.extendee() << " { " << field.name() << " = " << field.number() << " }"; @@ -189,17 +189,16 @@ template <typename Value> Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindExtension( const string& containing_type, int field_number) { - return FindWithDefault(by_extension_, - make_pair(containing_type, field_number), - Value()); + return FindWithDefault( + by_extension_, std::make_pair(containing_type, field_number), Value()); } template <typename Value> bool SimpleDescriptorDatabase::DescriptorIndex<Value>::FindAllExtensionNumbers( const string& containing_type, vector<int>* output) { - typename map<pair<string, int>, Value >::const_iterator it = - by_extension_.lower_bound(make_pair(containing_type, 0)); + typename map<pair<string, int>, Value>::const_iterator it = + by_extension_.lower_bound(std::make_pair(containing_type, 0)); bool success = false; for (; it != by_extension_.end() && it->first.first == containing_type; @@ -310,7 +309,7 @@ bool EncodedDescriptorDatabase::Add( const void* encoded_file_descriptor, int size) { FileDescriptorProto file; if (file.ParseFromArray(encoded_file_descriptor, size)) { - return index_.AddFile(file, make_pair(encoded_file_descriptor, size)); + return index_.AddFile(file, std::make_pair(encoded_file_descriptor, size)); } else { GOOGLE_LOG(ERROR) << "Invalid file descriptor data passed to " "EncodedDescriptorDatabase::Add()."; @@ -525,15 +524,16 @@ bool MergedDescriptorDatabase::FindAllExtensionNumbers( for (int i = 0; i < sources_.size(); i++) { if (sources_[i]->FindAllExtensionNumbers(extendee_type, &results)) { - copy(results.begin(), results.end(), - insert_iterator<set<int> >(merged_results, merged_results.begin())); + std::copy( + results.begin(), results.end(), + insert_iterator<set<int> >(merged_results, merged_results.begin())); success = true; } results.clear(); } - copy(merged_results.begin(), merged_results.end(), - insert_iterator<vector<int> >(*output, output->end())); + std::copy(merged_results.begin(), merged_results.end(), + insert_iterator<vector<int> >(*output, output->end())); return success; } diff --git a/src/google/protobuf/descriptor_database_unittest.cc b/src/google/protobuf/descriptor_database_unittest.cc index 6642d71b..1c03c443 100644 --- a/src/google/protobuf/descriptor_database_unittest.cc +++ b/src/google/protobuf/descriptor_database_unittest.cc @@ -408,7 +408,7 @@ TEST_P(DescriptorDatabaseTest, FindAllExtensionNumbers) { vector<int> numbers; EXPECT_TRUE(database_->FindAllExtensionNumbers("Foo", &numbers)); ASSERT_EQ(2, numbers.size()); - sort(numbers.begin(), numbers.end()); + std::sort(numbers.begin(), numbers.end()); EXPECT_EQ(5, numbers[0]); EXPECT_EQ(32, numbers[1]); } @@ -722,7 +722,7 @@ TEST_F(MergedDescriptorDatabaseTest, FindAllExtensionNumbers) { vector<int> numbers; EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Baz", &numbers)); ASSERT_EQ(2, numbers.size()); - sort(numbers.begin(), numbers.end()); + std::sort(numbers.begin(), numbers.end()); EXPECT_EQ(12, numbers[0]); EXPECT_EQ(13, numbers[1]); } @@ -731,7 +731,7 @@ TEST_F(MergedDescriptorDatabaseTest, FindAllExtensionNumbers) { vector<int> numbers; EXPECT_TRUE(reverse_merged_.FindAllExtensionNumbers("Baz", &numbers)); ASSERT_EQ(2, numbers.size()); - sort(numbers.begin(), numbers.end()); + std::sort(numbers.begin(), numbers.end()); EXPECT_EQ(12, numbers[0]); EXPECT_EQ(13, numbers[1]); } diff --git a/src/google/protobuf/descriptor_pb2_test.py b/src/google/protobuf/descriptor_pb2_test.py deleted file mode 100644 index c5a8d8a2..00000000 --- a/src/google/protobuf/descriptor_pb2_test.py +++ /dev/null @@ -1,54 +0,0 @@ -#! /usr/bin/python -# -# Protocol Buffers - Google's data interchange format -# Copyright 2008 Google Inc. All rights reserved. -# https://developers.google.com/protocol-buffers/ -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# Verify that prebuild and checkedin version of descriptor_pb2.py is up to date. - -from google3.pyglib import resources -from google.apputils import basetest - -_DESC = 'google3/net/proto2/proto/descriptor_pb2.' -_OLD = _DESC + 'py-prebuilt' -_NEW = _DESC + 'compiled' - - -class PregeneratedFileChanged(basetest.TestCase): - - def testSameText(self): - generated = resources.GetResource(_NEW) - checkedin = resources.GetResource(_OLD) - self.assertMultiLineEqual( - generated, checkedin, 'It seems that protoc _pb2 generator changed. ' - 'Please run google/protobuf/generate_descriptor_proto.sh to ' - 'regnerate a new version of %s and add it to your CL' % _OLD) - -if __name__ == '__main__': - basetest.main() diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc index 44277fa8..fdce3d78 100644 --- a/src/google/protobuf/descriptor_unittest.cc +++ b/src/google/protobuf/descriptor_unittest.cc @@ -5883,8 +5883,8 @@ class AbortingErrorCollector : public DescriptorPool::ErrorCollector { const Message *message, ErrorLocation location, const string &error_message) { - GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << ": " - << error_message; + GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << " [" + << element_name << "]: " << error_message; } private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AbortingErrorCollector); @@ -6104,9 +6104,9 @@ TEST_F(CopySourceCodeInfoToTest, CopySourceCodeInfoTo) { file_desc->CopySourceCodeInfoTo(&file_desc_proto); const SourceCodeInfo& info = file_desc_proto.source_code_info(); - ASSERT_EQ(3, info.location_size()); + ASSERT_EQ(4, info.location_size()); // Get the Foo message location - const SourceCodeInfo_Location& foo_location = info.location(1); + const SourceCodeInfo_Location& foo_location = info.location(2); ASSERT_EQ(2, foo_location.path_size()); EXPECT_EQ(FileDescriptorProto::kMessageTypeFieldNumber, foo_location.path(0)); EXPECT_EQ(0, foo_location.path(1)); // Foo is the first message defined diff --git a/src/google/protobuf/duration.proto b/src/google/protobuf/duration.proto new file mode 100644 index 00000000..12337f53 --- /dev/null +++ b/src/google/protobuf/duration.proto @@ -0,0 +1,94 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +syntax = "proto3"; + +package google.protobuf; + +option java_generate_equals_and_hash = true; +option java_multiple_files = true; +option java_outer_classname = "DurationProto"; +option java_package = "com.google.protobuf"; +option objc_class_prefix = "GPB"; + + +// A Duration represents a signed, fixed-length span of time represented +// as a count of seconds and fractions of seconds at nanosecond +// resolution. It is independent of any calendar and concepts like "day" +// or "month". It is related to Timestamp in that the difference between +// two Timestamp values is a Duration and it can be added or subtracted +// from a Timestamp. Range is approximately +-10,000 years. +// +// Example 1: Compute Duration from two Timestamps in pseudo code. +// +// Timestamp start = ...; +// Timestamp end = ...; +// Duration duration = ...; +// +// duration.seconds = end.seconds - start.seconds; +// duration.nanos = end.nanos - start.nanos; +// +// if (duration.seconds < 0 && duration.nanos > 0) { +// duration.seconds += 1; +// duration.nanos -= 1000000000; +// } else if (durations.seconds > 0 && duration.nanos < 0) { +// duration.seconds -= 1; +// duration.nanos += 1000000000; +// } +// +// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. +// +// Timestamp start = ...; +// Duration duration = ...; +// Timestamp end = ...; +// +// end.seconds = start.seconds + duration.seconds; +// end.nanos = start.nanos + duration.nanos; +// +// if (end.nanos < 0) { +// end.seconds -= 1; +// end.nanos += 1000000000; +// } else if (end.nanos >= 1000000000) { +// end.seconds += 1; +// end.nanos -= 1000000000; +// } +// +message Duration { + // Signed seconds of the span of time. Must be from -315,576,000,000 + // to +315,576,000,000 inclusive. + int64 seconds = 1; + + // Signed fractions of a second at nanosecond resolution of the span + // of time. Durations less than one second are represented with a 0 + // `seconds` field and a positive or negative `nanos` field. For durations + // of one second or more, a non-zero value for the `nanos` field must be + // of the same sign as the `seconds` field. Must be from -999,999,999 + // to +999,999,999 inclusive. + int32 nanos = 2; +} diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc index 565afaab..318ce6f9 100644 --- a/src/google/protobuf/dynamic_message.cc +++ b/src/google/protobuf/dynamic_message.cc @@ -218,6 +218,7 @@ class DynamicMessage : public Message { int oneof_case_offset; int unknown_fields_offset; int extensions_offset; + int is_default_instance_offset; // Not owned by the TypeInfo. DynamicMessageFactory* factory; // The factory that created this object. @@ -316,6 +317,11 @@ void DynamicMessage::SharedCtor() { uint32(0); } + if (type_info_->is_default_instance_offset != -1) { + *reinterpret_cast<bool*>( + OffsetToPointer(type_info_->is_default_instance_offset)) = false; + } + new(OffsetToPointer(type_info_->unknown_fields_offset)) UnknownFieldSet; if (type_info_->extensions_offset != -1) { @@ -532,6 +538,14 @@ void DynamicMessage::CrossLinkPrototypes() { factory->GetPrototypeNoLock(field->message_type()); } } + + // Set as the default instance -- this affects field-presence semantics for + // proto3. + if (type_info_->is_default_instance_offset != -1) { + void* is_default_instance_ptr = + OffsetToPointer(type_info_->is_default_instance_offset); + *reinterpret_cast<bool*>(is_default_instance_ptr) = true; + } } Message* DynamicMessage::New() const { @@ -641,11 +655,24 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( size = AlignOffset(size); // Next the has_bits, which is an array of uint32s. - type_info->has_bits_offset = size; - int has_bits_array_size = - DivideRoundingUp(type->field_count(), bitsizeof(uint32)); - size += has_bits_array_size * sizeof(uint32); - size = AlignOffset(size); + if (type->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) { + type_info->has_bits_offset = -1; + } else { + type_info->has_bits_offset = size; + int has_bits_array_size = + DivideRoundingUp(type->field_count(), bitsizeof(uint32)); + size += has_bits_array_size * sizeof(uint32); + size = AlignOffset(size); + } + + // The is_default_instance member, if any. + if (type->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) { + type_info->is_default_instance_offset = size; + size += sizeof(bool); + size = AlignOffset(size); + } else { + type_info->is_default_instance_offset = -1; + } // The oneof_case, if any. It is an array of uint32s. if (type->oneof_decl_count() > 0) { @@ -731,7 +758,8 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( type_info->pool, this, type_info->size, - -1 /* arena_offset */)); + -1 /* arena_offset */, + type_info->is_default_instance_offset)); } else { type_info->reflection.reset( new GeneratedMessageReflection( @@ -744,7 +772,8 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( type_info->pool, this, type_info->size, - -1 /* arena_offset */)); + -1 /* arena_offset */, + type_info->is_default_instance_offset)); } // Cross link prototypes. prototype->CrossLinkPrototypes(); diff --git a/src/google/protobuf/dynamic_message_unittest.cc b/src/google/protobuf/dynamic_message_unittest.cc index 6353ecbf..522a092a 100644 --- a/src/google/protobuf/dynamic_message_unittest.cc +++ b/src/google/protobuf/dynamic_message_unittest.cc @@ -46,6 +46,7 @@ #include <google/protobuf/descriptor.pb.h> #include <google/protobuf/test_util.h> #include <google/protobuf/unittest.pb.h> +#include <google/protobuf/unittest_no_field_presence.pb.h> #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> @@ -65,6 +66,8 @@ class DynamicMessageTest : public testing::Test { const Message* packed_prototype_; const Descriptor* oneof_descriptor_; const Message* oneof_prototype_; + const Descriptor* proto3_descriptor_; + const Message* proto3_prototype_; DynamicMessageTest(): factory_(&pool_) {} @@ -76,16 +79,20 @@ class DynamicMessageTest : public testing::Test { FileDescriptorProto unittest_file; FileDescriptorProto unittest_import_file; FileDescriptorProto unittest_import_public_file; + FileDescriptorProto unittest_no_field_presence_file; unittest::TestAllTypes::descriptor()->file()->CopyTo(&unittest_file); unittest_import::ImportMessage::descriptor()->file()->CopyTo( &unittest_import_file); unittest_import::PublicImportMessage::descriptor()->file()->CopyTo( &unittest_import_public_file); + proto2_nofieldpresence_unittest::TestAllTypes::descriptor()-> + file()->CopyTo(&unittest_no_field_presence_file); ASSERT_TRUE(pool_.BuildFile(unittest_import_public_file) != NULL); ASSERT_TRUE(pool_.BuildFile(unittest_import_file) != NULL); ASSERT_TRUE(pool_.BuildFile(unittest_file) != NULL); + ASSERT_TRUE(pool_.BuildFile(unittest_no_field_presence_file) != NULL); descriptor_ = pool_.FindMessageTypeByName("protobuf_unittest.TestAllTypes"); ASSERT_TRUE(descriptor_ != NULL); @@ -105,6 +112,12 @@ class DynamicMessageTest : public testing::Test { pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2"); ASSERT_TRUE(oneof_descriptor_ != NULL); oneof_prototype_ = factory_.GetPrototype(oneof_descriptor_); + + proto3_descriptor_ = + pool_.FindMessageTypeByName( + "proto2_nofieldpresence_unittest.TestAllTypes"); + ASSERT_TRUE(proto3_descriptor_ != NULL); + proto3_prototype_ = factory_.GetPrototype(proto3_descriptor_); } }; @@ -233,6 +246,40 @@ TEST_F(DynamicMessageTest, Arena) { // Return without freeing: should not leak. } +TEST_F(DynamicMessageTest, Proto3) { + Message* message = proto3_prototype_->New(); + const Reflection* refl = message->GetReflection(); + const Descriptor* desc = message->GetDescriptor(); + + // Just test a single primtive and single message field here to make sure we + // are getting the no-field-presence semantics elsewhere. DynamicMessage uses + // GeneratedMessageReflection under the hood, so the rest should be fine as + // long as GMR recognizes that we're using a proto3 message. + const FieldDescriptor* optional_int32 = + desc->FindFieldByName("optional_int32"); + const FieldDescriptor* optional_msg = + desc->FindFieldByName("optional_nested_message"); + EXPECT_TRUE(optional_int32 != NULL); + EXPECT_TRUE(optional_msg != NULL); + + EXPECT_EQ(false, refl->HasField(*message, optional_int32)); + refl->SetInt32(message, optional_int32, 42); + EXPECT_EQ(true, refl->HasField(*message, optional_int32)); + refl->SetInt32(message, optional_int32, 0); + EXPECT_EQ(false, refl->HasField(*message, optional_int32)); + + EXPECT_EQ(false, refl->HasField(*message, optional_msg)); + refl->MutableMessage(message, optional_msg); + EXPECT_EQ(true, refl->HasField(*message, optional_msg)); + delete refl->ReleaseMessage(message, optional_msg); + EXPECT_EQ(false, refl->HasField(*message, optional_msg)); + + // Also ensure that the default instance handles field presence properly. + EXPECT_EQ(false, refl->HasField(*proto3_prototype_, optional_msg)); + + delete message; +} + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/empty.proto b/src/google/protobuf/empty.proto new file mode 100644 index 00000000..94df0397 --- /dev/null +++ b/src/google/protobuf/empty.proto @@ -0,0 +1,50 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +syntax = "proto3"; + +package google.protobuf; + +option java_multiple_files = true; +option java_outer_classname = "EmptyProto"; +option java_package = "com.google.protobuf"; +option objc_class_prefix = "GPB"; + + +// A generic empty message that you can re-use to avoid defining duplicated +// empty messages in your APIs. A typical example is to use it as the request +// or the response type of an API method. For instance: +// +// service Foo { +// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); +// } +// +message Empty { + +} diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc index d6ebe4c3..03b38dd0 100644 --- a/src/google/protobuf/extension_set.cc +++ b/src/google/protobuf/extension_set.cc @@ -71,6 +71,8 @@ inline bool is_packable(WireFormatLite::WireType type) { // Do not add a default statement. Let the compiler complain when someone // adds a new wire type. } + GOOGLE_LOG(FATAL) << "can't reach here."; + return false; } // Registry stuff. @@ -95,7 +97,7 @@ void Register(const MessageLite* containing_type, int number, ExtensionInfo info) { ::google::protobuf::GoogleOnceInit(®istry_init_, &InitRegistry); - if (!InsertIfNotPresent(registry_, make_pair(containing_type, number), + if (!InsertIfNotPresent(registry_, std::make_pair(containing_type, number), info)) { GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \"" << containing_type->GetTypeName() @@ -105,8 +107,9 @@ void Register(const MessageLite* containing_type, const ExtensionInfo* FindRegisteredExtension( const MessageLite* containing_type, int number) { - return (registry_ == NULL) ? NULL : - FindOrNull(*registry_, make_pair(containing_type, number)); + return (registry_ == NULL) + ? NULL + : FindOrNull(*registry_, std::make_pair(containing_type, number)); } } // namespace @@ -1030,7 +1033,7 @@ void ExtensionSet::SwapExtension(ExtensionSet* other, if (this_iter == extensions_.end()) { if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { - extensions_.insert(make_pair(number, other_iter->second)); + extensions_.insert(std::make_pair(number, other_iter->second)); } else { InternalExtensionMergeFrom(number, other_iter->second); } @@ -1040,7 +1043,7 @@ void ExtensionSet::SwapExtension(ExtensionSet* other, if (other_iter == other->extensions_.end()) { if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { - other->extensions_.insert(make_pair(number, this_iter->second)); + other->extensions_.insert(std::make_pair(number, this_iter->second)); } else { other->InternalExtensionMergeFrom(number, this_iter->second); } @@ -1173,6 +1176,9 @@ bool ExtensionSet::ParseFieldWithExtensionInfo( extension.enum_validity_check.arg, value)) { AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, value, extension.descriptor); + } else { + // Invalid value. Treat as unknown. + field_skipper->SkipUnknownEnum(number, value); } } break; @@ -1335,7 +1341,7 @@ bool ExtensionSet::MaybeNewExtension(int number, const FieldDescriptor* descriptor, Extension** result) { pair<map<int, Extension>::iterator, bool> insert_result = - extensions_.insert(make_pair(number, Extension())); + extensions_.insert(std::make_pair(number, Extension())); *result = &insert_result.first->second; (*result)->descriptor = descriptor; return insert_result.second; diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc index 5f4ca1c3..796e7a5f 100644 --- a/src/google/protobuf/extension_set_heavy.cc +++ b/src/google/protobuf/extension_set_heavy.cc @@ -91,9 +91,10 @@ class DescriptorPoolExtensionFinder : public ExtensionFinder { const Descriptor* containing_type_; }; -void ExtensionSet::AppendToList(const Descriptor* containing_type, - const DescriptorPool* pool, - vector<const FieldDescriptor*>* output) const { +void ExtensionSet::AppendToList( + const Descriptor* containing_type, + const DescriptorPool* pool, + std::vector<const FieldDescriptor*>* output) const { for (map<int, Extension>::const_iterator iter = extensions_.begin(); iter != extensions_.end(); ++iter) { bool has = false; diff --git a/src/google/protobuf/field_mask.proto b/src/google/protobuf/field_mask.proto new file mode 100644 index 00000000..081c004a --- /dev/null +++ b/src/google/protobuf/field_mask.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; + +option java_multiple_files = true; +option java_outer_classname = "FieldMaskProto"; +option java_package = "com.google.protobuf"; +option objc_class_prefix = "GPB"; + + +// `FieldMask` represents a set of symbolic field paths, for example: +// +// paths: "f.a" +// paths: "f.b.d" +// +// Here `f` represents a field in some root message, `a` and `b` +// fields in the message found in `f`, and `d` a field found in the +// message in `f.b`. +// +// Field masks are used to specify a subset of fields that should be +// returned by a get operation or modified by an update operation. +// Field masks also have a custom JSON encoding (see below). +// +// # Field Masks in Projections +// When used in the context of a projection, a response message or +// sub-message is filtered by the API to only contain those fields as +// specified in the mask. For example, if the mask in the previous +// example is applied to a response message as follows: +// +// f { +// a : 22 +// b { +// d : 1 +// x : 2 +// } +// y : 13 +// } +// z: 8 +// +// The result will not contain specific values for fields x,y and z +// (there value will be set to the default, and omitted in proto text +// output): +// +// +// f { +// a : 22 +// b { +// d : 1 +// } +// } +// +// A repeated field is not allowed except at the last position of a +// field mask. +// +// If a FieldMask object is not present in a get operation, the +// operation applies to all fields (as if a FieldMask of all fields +// had been specified). +// +// Note that a field mask does not necessarily applies to the +// top-level response message. In case of a REST get operation, the +// field mask applies directly to the response, but in case of a REST +// list operation, the mask instead applies to each individual message +// in the returned resource list. In case of a REST custom method, +// other definitions may be used. Where the mask applies will be +// clearly documented together with its declaration in the API. In +// any case, the effect on the returned resource/resources is required +// behavior for APIs. +// +// # Field Masks in Update Operations +// A field mask in update operations specifies which fields of the +// targeted resource are going to be updated. The API is required +// to only change the values of the fields as specified in the mask +// and leave the others untouched. If a resource is passed in to +// describe the updated values, the API ignores the values of all +// fields not covered by the mask. +// +// In order to reset a field's value to the default, the field must +// be in the mask and set to the default value in the provided resource. +// Hence, in order to reset all fields of a resource, provide a default +// instance of the resource and set all fields in the mask, or do +// not provide a mask as described below. +// +// If a field mask is not present on update, the operation applies to +// all fields (as if a field mask of all fields has been specified). +// Note that in the presence of schema evolution, this may mean that +// fields the client does not know and has therefore not filled into +// the request will be reset to their default. If this is unwanted +// behavior, a specific service may require a client to always specify +// a field mask, producing an error if not. +// +// As with get operations, the location of the resource which +// describes the updated values in the request message depends on the +// operation kind. In any case, the effect of the field mask is +// required to be honored by the API. +// +// ## Considerations for HTTP REST +// The HTTP kind of an update operation which uses a field mask must +// be set to PATCH instead of PUT in order to satisfy HTTP semantics +// (PUT must only be used for full updates). +// +// # JSON Encoding of Field Masks +// In JSON, a field mask is encoded as a single string where paths are +// separated by a comma. Fields name in each path are converted +// to/from lower-camel naming conventions. +// +// As an example, consider the following message declarations: +// +// message Profile { +// User user = 1; +// Photo photo = 2; +// } +// message User { +// string display_name = 1; +// string address = 2; +// } +// +// In proto a field mask for `Profile` may look as such: +// +// mask { +// paths: "user.display_name" +// paths: "photo" +// } +// +// In JSON, the same mask is represented as below: +// +// { +// mask: "user.displayName,photo" +// } +// +message FieldMask { + // The set of field mask paths. + repeated string paths = 1; +} diff --git a/src/google/protobuf/generated_enum_reflection.h b/src/google/protobuf/generated_enum_reflection.h index 3852cea5..fdcdc277 100644 --- a/src/google/protobuf/generated_enum_reflection.h +++ b/src/google/protobuf/generated_enum_reflection.h @@ -42,6 +42,7 @@ #include <string> #include <google/protobuf/stubs/template_util.h> +#include <google/protobuf/generated_enum_util.h> namespace google { namespace protobuf { @@ -50,10 +51,6 @@ namespace protobuf { namespace protobuf { -// This type trait can be used to cause templates to only match proto2 enum -// types. -template <typename T> struct is_proto_enum : ::google::protobuf::internal::false_type {}; - // Returns the EnumDescriptor for enum type E, which must be a // proto-declared enum type. Code generated by the protocol compiler // will include specializations of this template for each enum type declared. diff --git a/src/google/protobuf/generated_enum_util.h b/src/google/protobuf/generated_enum_util.h new file mode 100644 index 00000000..e4242055 --- /dev/null +++ b/src/google/protobuf/generated_enum_util.h @@ -0,0 +1,46 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__ +#define GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__ + +#include <google/protobuf/stubs/template_util.h> + +namespace google { +namespace protobuf { + +// This type trait can be used to cause templates to only match proto2 enum +// types. +template <typename T> struct is_proto_enum : ::google::protobuf::internal::false_type {}; + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__ diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index a20e362c..412c48a1 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -193,7 +193,8 @@ GeneratedMessageReflection::GeneratedMessageReflection( const DescriptorPool* descriptor_pool, MessageFactory* factory, int object_size, - int arena_offset) + int arena_offset, + int is_default_instance_offset) : descriptor_ (descriptor), default_instance_ (default_instance), offsets_ (offsets), @@ -201,6 +202,7 @@ GeneratedMessageReflection::GeneratedMessageReflection( unknown_fields_offset_(unknown_fields_offset), extensions_offset_(extensions_offset), arena_offset_ (arena_offset), + is_default_instance_offset_(is_default_instance_offset), object_size_ (object_size), descriptor_pool_ ((descriptor_pool == NULL) ? DescriptorPool::generated_pool() : @@ -220,7 +222,8 @@ GeneratedMessageReflection::GeneratedMessageReflection( const DescriptorPool* descriptor_pool, MessageFactory* factory, int object_size, - int arena_offset) + int arena_offset, + int is_default_instance_offset) : descriptor_ (descriptor), default_instance_ (default_instance), default_oneof_instance_ (default_oneof_instance), @@ -230,6 +233,7 @@ GeneratedMessageReflection::GeneratedMessageReflection( unknown_fields_offset_(unknown_fields_offset), extensions_offset_(extensions_offset), arena_offset_ (arena_offset), + is_default_instance_offset_(is_default_instance_offset), object_size_ (object_size), descriptor_pool_ ((descriptor_pool == NULL) ? DescriptorPool::generated_pool() : @@ -243,8 +247,14 @@ namespace { UnknownFieldSet* empty_unknown_field_set_ = NULL; GOOGLE_PROTOBUF_DECLARE_ONCE(empty_unknown_field_set_once_); +void DeleteEmptyUnknownFieldSet() { + delete empty_unknown_field_set_; + empty_unknown_field_set_ = NULL; +} + void InitEmptyUnknownFieldSet() { empty_unknown_field_set_ = new UnknownFieldSet; + internal::OnShutdown(&DeleteEmptyUnknownFieldSet); } const UnknownFieldSet& GetEmptyUnknownFieldSet() { @@ -483,11 +493,11 @@ void GeneratedMessageReflection::SwapOneofField( double temp_double; bool temp_bool; int temp_int; - Message* temp_message; + Message* temp_message = NULL; string temp_string; // Stores message1's oneof field to a temp variable. - const FieldDescriptor* field1; + const FieldDescriptor* field1 = NULL; if (oneof_case1 > 0) { field1 = descriptor_->FindFieldByNumber(oneof_case1); //oneof_descriptor->field(oneof_case1); @@ -985,6 +995,7 @@ void GeneratedMessageReflection::ListFields( // Optimization: The default instance never has any fields set. if (&message == default_instance_) return; + output->reserve(descriptor_->field_count()); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); if (field->is_repeated()) { @@ -1008,7 +1019,7 @@ void GeneratedMessageReflection::ListFields( } // ListFields() must sort output by field number. - sort(output->begin(), output->end(), FieldNumberSorter()); + std::sort(output->begin(), output->end(), FieldNumberSorter()); } // ------------------------------------------------------------------- @@ -1424,6 +1435,8 @@ const Message& GeneratedMessageReflection::GetMessage( Message* GeneratedMessageReflection::MutableMessage( Message* message, const FieldDescriptor* field, MessageFactory* factory) const { + USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE); + if (factory == NULL) factory = message_factory_; if (field->is_extension()) { @@ -1829,6 +1842,17 @@ GeneratedMessageReflection::MutableInternalMetadataWithArena( return reinterpret_cast<InternalMetadataWithArena*>(ptr); } +inline bool +GeneratedMessageReflection::GetIsDefaultInstance( + const Message& message) const { + if (is_default_instance_offset_ == kHasNoDefaultInstanceField) { + return false; + } + const void* ptr = reinterpret_cast<const uint8*>(&message) + + is_default_instance_offset_; + return *reinterpret_cast<const bool*>(ptr); +} + // Simple accessors for manipulating has_bits_. inline bool GeneratedMessageReflection::HasBit( const Message& message, const FieldDescriptor* field) const { @@ -1836,7 +1860,8 @@ inline bool GeneratedMessageReflection::HasBit( // proto3: no has-bits. All fields present except messages, which are // present only if their message-field pointer is non-NULL. if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - return GetRaw<const Message*>(message, field) != NULL; + return !GetIsDefaultInstance(message) && + GetRaw<const Message*>(message, field) != NULL; } else { // Non-message field (and non-oneof, since that was handled in HasField() // before calling us), and singular (again, checked in HasField). So, this @@ -1950,26 +1975,28 @@ inline void GeneratedMessageReflection::ClearOneof( uint32 oneof_case = GetOneofCase(*message, oneof_descriptor); if (oneof_case > 0) { const FieldDescriptor* field = descriptor_->FindFieldByNumber(oneof_case); - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_STRING: { - switch (field->options().ctype()) { - default: // TODO(kenton): Support other string reps. - case FieldOptions::STRING: { - const string* default_ptr = - &DefaultRaw<ArenaStringPtr>(field).Get(NULL); - MutableField<ArenaStringPtr>(message, field)-> - Destroy(default_ptr, GetArena(message)); - break; + if (GetArena(message) == NULL) { + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_STRING: { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: { + const string* default_ptr = + &DefaultRaw<ArenaStringPtr>(field).Get(NULL); + MutableField<ArenaStringPtr>(message, field)-> + Destroy(default_ptr, GetArena(message)); + break; + } } + break; } - break; - } - case FieldDescriptor::CPPTYPE_MESSAGE: - delete *MutableRaw<Message*>(message, field); - break; - default: - break; + case FieldDescriptor::CPPTYPE_MESSAGE: + delete *MutableRaw<Message*>(message, field); + break; + default: + break; + } } *MutableOneofCase(message, oneof_descriptor) = 0; @@ -2082,7 +2109,8 @@ GeneratedMessageReflection::NewGeneratedMessageReflection( const void* default_oneof_instance, int oneof_case_offset, int object_size, - int arena_offset) { + int arena_offset, + int is_default_instance_offset) { return new GeneratedMessageReflection(descriptor, default_instance, offsets, @@ -2094,7 +2122,8 @@ GeneratedMessageReflection::NewGeneratedMessageReflection( DescriptorPool::generated_pool(), MessageFactory::generated_factory(), object_size, - arena_offset); + arena_offset, + is_default_instance_offset); } GeneratedMessageReflection* @@ -2106,7 +2135,8 @@ GeneratedMessageReflection::NewGeneratedMessageReflection( int unknown_fields_offset, int extensions_offset, int object_size, - int arena_offset) { + int arena_offset, + int is_default_instance_offset) { return new GeneratedMessageReflection(descriptor, default_instance, offsets, @@ -2116,7 +2146,8 @@ GeneratedMessageReflection::NewGeneratedMessageReflection( DescriptorPool::generated_pool(), MessageFactory::generated_factory(), object_size, - arena_offset); + arena_offset, + is_default_instance_offset); } } // namespace internal diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h index 306809da..4dddf6c7 100644 --- a/src/google/protobuf/generated_message_reflection.h +++ b/src/google/protobuf/generated_message_reflection.h @@ -136,7 +136,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { const DescriptorPool* pool, MessageFactory* factory, int object_size, - int arena_offset); + int arena_offset, + int is_default_instance_offset = -1); // Similar with the construction above. Call this construction if the // message has oneof definition. @@ -173,7 +174,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { const DescriptorPool* pool, MessageFactory* factory, int object_size, - int arena_offset); + int arena_offset, + int is_default_instance_offset = -1); ~GeneratedMessageReflection(); // Shorter-to-call helpers for the above two constructions that work if the @@ -190,7 +192,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { const void* default_oneof_instance, int oneof_case_offset, int object_size, - int arena_offset); + int arena_offset, + int is_default_instance_offset = -1); static GeneratedMessageReflection* NewGeneratedMessageReflection( const Descriptor* descriptor, @@ -200,7 +203,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { int unknown_fields_offset, int extensions_offset, int object_size, - int arena_offset); + int arena_offset, + int is_default_instance_offset = -1); // implements Reflection ------------------------------------------- @@ -414,8 +418,11 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { int unknown_fields_offset_; int extensions_offset_; int arena_offset_; + int is_default_instance_offset_; int object_size_; + static const int kHasNoDefaultInstanceField = -1; + const DescriptorPool* descriptor_pool_; MessageFactory* message_factory_; @@ -446,6 +453,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { inline internal::InternalMetadataWithArena* MutableInternalMetadataWithArena(Message* message) const; + inline bool GetIsDefaultInstance(const Message& message) const; + inline bool HasBit(const Message& message, const FieldDescriptor* field) const; inline void SetBit(Message* message, diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc index df88205c..93e1a22e 100644 --- a/src/google/protobuf/io/coded_stream.cc +++ b/src/google/protobuf/io/coded_stream.cc @@ -153,7 +153,7 @@ void CodedInputStream::PopLimit(Limit limit) { std::pair<CodedInputStream::Limit, int> CodedInputStream::IncrementRecursionDepthAndPushLimit(int byte_limit) { - return make_pair(PushLimit(byte_limit), --recursion_budget_); + return std::make_pair(PushLimit(byte_limit), --recursion_budget_); } bool CodedInputStream::DecrementRecursionDepthAndPopLimit(Limit limit) { @@ -613,8 +613,15 @@ CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output) } CodedOutputStream::~CodedOutputStream() { + Trim(); +} + +void CodedOutputStream::Trim() { if (buffer_size_ > 0) { output_->BackUp(buffer_size_); + total_bytes_ -= buffer_size_; + buffer_size_ = 0; + buffer_ = NULL; } } @@ -662,12 +669,7 @@ void CodedOutputStream::WriteAliasedRaw(const void* data, int size) { ) { WriteRaw(data, size); } else { - if (buffer_size_ > 0) { - output_->BackUp(buffer_size_); - total_bytes_ -= buffer_size_; - buffer_ = NULL; - buffer_size_ = 0; - } + Trim(); total_bytes_ += size; had_error_ |= !output_->WriteAliasedRaw(data, size); @@ -704,61 +706,12 @@ void CodedOutputStream::WriteLittleEndian64(uint64 value) { } } -inline uint8* CodedOutputStream::WriteVarint32FallbackToArrayInline( - uint32 value, uint8* target) { - target[0] = static_cast<uint8>(value | 0x80); - if (value >= (1 << 7)) { - target[1] = static_cast<uint8>((value >> 7) | 0x80); - if (value >= (1 << 14)) { - target[2] = static_cast<uint8>((value >> 14) | 0x80); - if (value >= (1 << 21)) { - target[3] = static_cast<uint8>((value >> 21) | 0x80); - if (value >= (1 << 28)) { - target[4] = static_cast<uint8>(value >> 28); - return target + 5; - } else { - target[3] &= 0x7F; - return target + 4; - } - } else { - target[2] &= 0x7F; - return target + 3; - } - } else { - target[1] &= 0x7F; - return target + 2; - } - } else { - target[0] &= 0x7F; - return target + 1; - } -} - -void CodedOutputStream::WriteVarint32(uint32 value) { - if (buffer_size_ >= kMaxVarint32Bytes) { - // Fast path: We have enough bytes left in the buffer to guarantee that - // this write won't cross the end, so we can skip the checks. - uint8* target = buffer_; - uint8* end = WriteVarint32FallbackToArrayInline(value, target); - int size = end - target; - Advance(size); - } else { - // Slow path: This write might cross the end of the buffer, so we - // compose the bytes first then use WriteRaw(). - uint8 bytes[kMaxVarint32Bytes]; - int size = 0; - while (value > 0x7F) { - bytes[size++] = (static_cast<uint8>(value) & 0x7F) | 0x80; - value >>= 7; - } - bytes[size++] = static_cast<uint8>(value) & 0x7F; - WriteRaw(bytes, size); - } -} - -uint8* CodedOutputStream::WriteVarint32FallbackToArray( - uint32 value, uint8* target) { - return WriteVarint32FallbackToArrayInline(value, target); +void CodedOutputStream::WriteVarint32SlowPath(uint32 value) { + uint8 bytes[kMaxVarint32Bytes]; + uint8* target = &bytes[0]; + uint8* end = WriteVarint32ToArray(value, target); + int size = end - target; + WriteRaw(bytes, size); } inline uint8* CodedOutputStream::WriteVarint64ToArrayInline( diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h index b9c30fa3..dea4b650 100644 --- a/src/google/protobuf/io/coded_stream.h +++ b/src/google/protobuf/io/coded_stream.h @@ -123,7 +123,8 @@ #endif #else #include <sys/param.h> // __BYTE_ORDER - #if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN && \ + #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 @@ -646,6 +647,13 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { // ZeroCopyOutputStream immediately after the last byte written. ~CodedOutputStream(); + // Trims any unused space in the underlying buffer so that its size matches + // the number of bytes written by this stream. The underlying buffer will + // automatically be trimmed when this stream is destroyed; this call is only + // necessary if the underlying buffer is accessed *before* the stream is + // destroyed. + void Trim(); + // Skips a number of bytes, leaving the bytes unmodified in the underlying // buffer. Returns false if an underlying write error occurs. This is // mainly useful with GetDirectBufferPointer(). @@ -788,7 +796,9 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { // ZeroCopyOutputStream supports it. void WriteAliasedRaw(const void* buffer, int size); - static uint8* WriteVarint32FallbackToArray(uint32 value, uint8* target); + // If this write might cross the end of the buffer, we compose the bytes first + // then use WriteRaw(). + void WriteVarint32SlowPath(uint32 value); // Always-inlined versions of WriteVarint* functions so that code can be // reused, while still controlling size. For instance, WriteVarint32ToArray() @@ -797,8 +807,6 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { // WriteVarint32FallbackToArray. Meanwhile, WriteVarint32() is already // out-of-line, so it should just invoke this directly to avoid any extra // function call overhead. - static uint8* WriteVarint32FallbackToArrayInline( - uint32 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; static uint8* WriteVarint64ToArrayInline( uint64 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; @@ -918,7 +926,7 @@ inline std::pair<uint32, bool> CodedInputStream::ReadTagWithCutoff( const uint32 kMax1ByteVarint = 0x7f; uint32 tag = last_tag_ = buffer_[0]; Advance(1); - return make_pair(tag, cutoff >= kMax1ByteVarint || tag <= cutoff); + return std::make_pair(tag, cutoff >= kMax1ByteVarint || tag <= cutoff); } // Other hot case: cutoff >= 0x80, buffer_ has at least two bytes available, // and tag is two bytes. The latter is tested by bitwise-and-not of the @@ -936,12 +944,12 @@ inline std::pair<uint32, bool> CodedInputStream::ReadTagWithCutoff( // so we don't have to check for tag == 0. We may need to check whether // it exceeds cutoff. bool at_or_below_cutoff = cutoff >= kMax2ByteVarint || tag <= cutoff; - return make_pair(tag, at_or_below_cutoff); + return std::make_pair(tag, at_or_below_cutoff); } } // Slow path last_tag_ = ReadTagFallback(); - return make_pair(last_tag_, static_cast<uint32>(last_tag_ - 1) < cutoff); + return std::make_pair(last_tag_, static_cast<uint32>(last_tag_ - 1) < cutoff); } inline bool CodedInputStream::LastTagWas(uint32 expected) { @@ -1026,13 +1034,14 @@ inline uint8* CodedOutputStream::GetDirectBufferForNBytesAndAdvance(int size) { } inline uint8* CodedOutputStream::WriteVarint32ToArray(uint32 value, - uint8* target) { - if (value < 0x80) { - *target = value; - return target + 1; - } else { - return WriteVarint32FallbackToArray(value, target); + uint8* target) { + while (value >= 0x80) { + *target = static_cast<uint8>(value | 0x80); + value >>= 7; + ++target; } + *target = static_cast<uint8>(value); + return target + 1; } inline void CodedOutputStream::WriteVarint32SignExtended(int32 value) { @@ -1085,22 +1094,26 @@ inline uint8* CodedOutputStream::WriteLittleEndian64ToArray(uint64 value, return target + sizeof(value); } +inline void CodedOutputStream::WriteVarint32(uint32 value) { + if (buffer_size_ >= 5) { + // Fast path: We have enough bytes left in the buffer to guarantee that + // this write won't cross the end, so we can skip the checks. + uint8* target = buffer_; + uint8* end = WriteVarint32ToArray(value, target); + int size = end - target; + Advance(size); + } else { + WriteVarint32SlowPath(value); + } +} + inline void CodedOutputStream::WriteTag(uint32 value) { WriteVarint32(value); } inline uint8* CodedOutputStream::WriteTagToArray( uint32 value, uint8* target) { - if (value < (1 << 7)) { - target[0] = value; - return target + 1; - } else if (value < (1 << 14)) { - target[0] = static_cast<uint8>(value | 0x80); - target[1] = static_cast<uint8>(value >> 7); - return target + 2; - } else { - return WriteVarint32FallbackToArray(value, target); - } + return WriteVarint32ToArray(value, target); } inline int CodedOutputStream::VarintSize32(uint32 value) { diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc index bbe5e399..02d5bad3 100644 --- a/src/google/protobuf/io/coded_stream_unittest.cc +++ b/src/google/protobuf/io/coded_stream_unittest.cc @@ -502,11 +502,11 @@ struct Fixed64Case { }; inline std::ostream& operator<<(std::ostream& os, const Fixed32Case& c) { - return os << "0x" << hex << c.value << dec; + return os << "0x" << std::hex << c.value << std::dec; } inline std::ostream& operator<<(std::ostream& os, const Fixed64Case& c) { - return os << "0x" << hex << c.value << dec; + return os << "0x" << std::hex << c.value << std::dec; } Fixed32Case kFixed32Cases[] = { diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc index e6037863..c9f4ca7f 100644 --- a/src/google/protobuf/io/gzip_stream.cc +++ b/src/google/protobuf/io/gzip_stream.cc @@ -49,6 +49,7 @@ static const int kDefaultBufferSize = 65536; GzipInputStream::GzipInputStream( ZeroCopyInputStream* sub_stream, Format format, int buffer_size) : format_(format), sub_stream_(sub_stream), zerror_(Z_OK), byte_count_(0) { + zcontext_.state = Z_NULL; zcontext_.zalloc = Z_NULL; zcontext_.zfree = Z_NULL; zcontext_.opaque = Z_NULL; diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/src/google/protobuf/io/zero_copy_stream_impl_lite.h index 3e25edfa..4360b18f 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h @@ -368,7 +368,7 @@ inline char* mutable_string_data(string* s) { inline std::pair<char*, bool> as_string_data(string* s) { char *p = mutable_string_data(s); #ifdef LANG_CXX11 - return make_pair(p, true); + return std::make_pair(p, true); #else return make_pair(p, p != NULL); #endif diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc index a3705269..4ea21007 100644 --- a/src/google/protobuf/lite_unittest.cc +++ b/src/google/protobuf/lite_unittest.cc @@ -345,6 +345,6 @@ int main(int argc, char* argv[]) { GOOGLE_CHECK_EQ(0, empty_message.unknown_fields().size()); } - cout << "PASS" << endl; + std::cout << "PASS" << std::endl; return 0; } diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h index e55a6d43..e56af3fc 100644 --- a/src/google/protobuf/map.h +++ b/src/google/protobuf/map.h @@ -34,6 +34,8 @@ #include <iterator> #include <google/protobuf/stubs/hash.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/generated_enum_util.h> #include <google/protobuf/map_type_handler.h> namespace google { @@ -45,10 +47,12 @@ class Map; template <typename Enum> struct is_proto_enum; namespace internal { -template <typename K, typename V, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> -class MapField; -} // namespace internal +template <typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type, + int default_enum_value> +class MapFieldLite; +} // This is the class for google::protobuf::Map's internal value_type. Instead of using // std::pair as value_type, we use this class which provides us more control of @@ -56,29 +60,29 @@ class MapField; template <typename Key, typename T> class MapPair { public: - typedef Key first_type; + typedef const Key first_type; typedef T second_type; MapPair(const Key& other_first, const T& other_second) : first(other_first), second(other_second) {} - explicit MapPair(const Key& other_first) : first(other_first), second() {} - MapPair(const MapPair& other) : first(other.first), second(other.second) {} - MapPair& operator=(const MapPair& other) { - first = other.first; - second = other.second; - return *this; - } - ~MapPair() {} + // Implicitly convertible to std::pair of compatible types. + template <typename T1, typename T2> + operator std::pair<T1, T2>() const { + return std::pair<T1, T2>(first, second); + } + const Key first; T second; private: + typedef void DestructorSkippable_; + friend class ::google::protobuf::Arena; friend class Map<Key, T>; }; @@ -87,6 +91,7 @@ class MapPair { // interface directly to visit or change map fields. template <typename Key, typename T> class Map { + typedef internal::MapCppTypeHandler<Key> KeyTypeHandler; typedef internal::MapCppTypeHandler<T> ValueTypeHandler; public: @@ -101,20 +106,104 @@ class Map { typedef size_t size_type; typedef hash<Key> hasher; - - Map() : default_enum_value_(0) {} - - Map(const Map& other) { + typedef equal_to<Key> key_equal; + + Map() + : arena_(NULL), + allocator_(arena_), + elements_(0, hasher(), key_equal(), allocator_), + default_enum_value_(0) {} + explicit Map(Arena* arena) + : arena_(arena), + allocator_(arena_), + elements_(0, hasher(), key_equal(), allocator_), + default_enum_value_(0) {} + + Map(const Map& other) + : arena_(NULL), + allocator_(arena_), + elements_(0, hasher(), key_equal(), allocator_), + default_enum_value_(other.default_enum_value_) { insert(other.begin(), other.end()); } ~Map() { clear(); } + private: + // re-implement std::allocator to use arena allocator for memory allocation. + // Used for google::protobuf::Map implementation. Users should not use this class + // directly. + template <typename U> + class MapAllocator { + public: + typedef U value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + MapAllocator() : arena_(NULL) {} + explicit MapAllocator(Arena* arena) : arena_(arena) {} + template <typename X> + MapAllocator(const MapAllocator<X>& allocator) + : arena_(allocator.arena_) {} + + pointer allocate(size_type n, const_pointer hint = 0) { + // If arena is not given, malloc needs to be called which doesn't + // construct element object. + if (arena_ == NULL) { + return reinterpret_cast<pointer>(malloc(n * sizeof(value_type))); + } else { + return reinterpret_cast<pointer>( + Arena::CreateArray<uint8>(arena_, n * sizeof(value_type))); + } + } + + void deallocate(pointer p, size_type n) { + if (arena_ == NULL) { + free(p); + } + } + + void construct(pointer p, const_reference t) { new (p) value_type(t); } + + void destroy(pointer p) { + if (arena_ == NULL) p->~value_type(); + } + + template <typename X> + struct rebind { + typedef MapAllocator<X> other; + }; + + template <typename X> + bool operator==(const MapAllocator<X>& other) const { + return arena_ == other.arena_; + } + + template <typename X> + bool operator!=(const MapAllocator<X>& other) const { + return arena_ != other.arena_; + } + + private: + Arena* arena_; + + template <typename X> + friend class MapAllocator; + }; + + public: + typedef MapAllocator<std::pair<const Key, MapPair<Key, T>*> > Allocator; + // Iterators class LIBPROTOBUF_EXPORT const_iterator : public std::iterator<std::forward_iterator_tag, value_type, ptrdiff_t, const value_type*, const value_type&> { - typedef typename hash_map<Key, value_type*>::const_iterator InnerIt; + typedef typename hash_map<Key, value_type*, hash<Key>, equal_to<Key>, + Allocator>::const_iterator InnerIt; public: const_iterator() {} @@ -141,7 +230,8 @@ class Map { }; class LIBPROTOBUF_EXPORT iterator : public std::iterator<std::forward_iterator_tag, value_type> { - typedef typename hash_map<Key, value_type*>::iterator InnerIt; + typedef typename hash_map<Key, value_type*, hasher, equal_to<Key>, + Allocator>::iterator InnerIt; public: iterator() {} @@ -186,7 +276,7 @@ class Map { T& operator[](const key_type& key) { value_type** value = &elements_[key]; if (*value == NULL) { - *value = new value_type(key); + *value = CreateValueTypeInternal(key); internal::MapValueInitializer<google::protobuf::is_proto_enum<T>::value, T>::Initialize((*value)->second, default_enum_value_); @@ -242,7 +332,7 @@ class Map { } else { return std::pair<iterator, bool>( iterator(elements_.insert(std::pair<Key, value_type*>( - value.first, new value_type(value))).first), true); + value.first, CreateValueTypeInternal(value))).first), true); } } template <class InputIt> @@ -257,28 +347,29 @@ class Map { // Erase size_type erase(const key_type& key) { - typename hash_map<Key, value_type*>::iterator it = elements_.find(key); + typename hash_map<Key, value_type*, hash<Key>, equal_to<Key>, + Allocator>::iterator it = elements_.find(key); if (it == elements_.end()) { return 0; } else { - delete it->second; + if (arena_ == NULL) delete it->second; elements_.erase(it); return 1; } } void erase(iterator pos) { - delete pos.it_->second; + if (arena_ == NULL) delete pos.it_->second; elements_.erase(pos.it_); } void erase(iterator first, iterator last) { for (iterator it = first; it != last;) { - delete it.it_->second; + if (arena_ == NULL) delete it.it_->second; elements_.erase((it++).it_); } } void clear() { for (iterator it = begin(); it != end(); ++it) { - delete it.it_->second; + if (arena_ == NULL) delete it.it_->second; } elements_.clear(); } @@ -298,12 +389,45 @@ class Map { default_enum_value_ = default_enum_value; } - hash_map<Key, value_type*> elements_; + value_type* CreateValueTypeInternal(const Key& key) { + if (arena_ == NULL) { + return new value_type(key); + } else { + value_type* value = reinterpret_cast<value_type*>( + Arena::CreateArray<uint8>(arena_, sizeof(value_type))); + Arena::CreateInArenaStorage(const_cast<Key*>(&value->first), arena_); + Arena::CreateInArenaStorage(&value->second, arena_); + const_cast<Key&>(value->first) = key; + return value; + } + } + + value_type* CreateValueTypeInternal(const value_type& value) { + if (arena_ == NULL) { + return new value_type(value); + } else { + value_type* p = reinterpret_cast<value_type*>( + Arena::CreateArray<uint8>(arena_, sizeof(value_type))); + Arena::CreateInArenaStorage(const_cast<Key*>(&p->first), arena_); + Arena::CreateInArenaStorage(&p->second, arena_); + const_cast<Key&>(p->first) = value.first; + p->second = value.second; + return p; + } + } + + Arena* arena_; + Allocator allocator_; + hash_map<Key, value_type*, hash<Key>, equal_to<Key>, Allocator> elements_; int default_enum_value_; - template <typename K, typename V, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum> - friend class LIBPROTOBUF_EXPORT internal::MapField; + friend class ::google::protobuf::Arena; + typedef void DestructorSkippable_; + template <typename K, typename V, + internal::WireFormatLite::FieldType key_wire_type, + internal::WireFormatLite::FieldType value_wire_type, + int default_enum_value> + friend class LIBPROTOBUF_EXPORT internal::MapFieldLite; }; } // namespace protobuf diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h index 6971c763..f78a4f40 100644 --- a/src/google/protobuf/map_entry.h +++ b/src/google/protobuf/map_entry.h @@ -31,18 +31,33 @@ #ifndef GOOGLE_PROTOBUF_MAP_ENTRY_H__ #define GOOGLE_PROTOBUF_MAP_ENTRY_H__ -#include <google/protobuf/reflection_ops.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/map_entry_lite.h> #include <google/protobuf/map_type_handler.h> +#include <google/protobuf/reflection_ops.h> +#include <google/protobuf/unknown_field_set.h> #include <google/protobuf/wire_format_lite_inl.h> namespace google { namespace protobuf { class Arena; +namespace internal { +template <typename Key, typename Value, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> +class MapField; +} } namespace protobuf { namespace internal { +// Register all MapEntry default instances so we can delete them in +// ShutdownProtobufLibrary(). +void LIBPROTOBUF_EXPORT RegisterMapEntryDefaultInstance( + MessageLite* default_instance); + // This is the common base class for MapEntry. It is used by MapFieldBase in // reflection api, in which the static type of key and value is unknown. class LIBPROTOBUF_EXPORT MapEntryBase : public Message { @@ -78,179 +93,103 @@ class LIBPROTOBUF_EXPORT MapEntryBase : public Message { // while we need to explicitly tell cpp type if proto type is TYPE_MESSAGE to // get internal layout. // Moreover, default_enum_value is used to initialize enum field in proto2. -template <typename Key, typename Value, FieldDescriptor::Type KeyProtoType, - FieldDescriptor::Type ValueProtoType, int default_enum_value> +template <typename Key, typename Value, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> class LIBPROTOBUF_EXPORT MapEntry : public MapEntryBase { - // Handlers for key/value's proto field type. Used to infer internal layout - // and provide parsing/serialization support. - typedef MapProtoTypeHandler<KeyProtoType> KeyProtoHandler; - typedef MapProtoTypeHandler<ValueProtoType> ValueProtoHandler; + // Handlers for key/value wire type. Provide utilities to parse/serialize + // key/value. + typedef MapWireFieldTypeHandler<kKeyFieldType> KeyWireHandler; + typedef MapWireFieldTypeHandler<kValueFieldType> ValueWireHandler; // Define key/value's internal stored type. Message is the only one whose // internal stored type cannot be inferred from its proto type. - typedef typename KeyProtoHandler::CppType KeyProtoHandlerCppType; - typedef typename ValueProtoHandler::CppType ValueProtoHandlerCppType; - static const bool kIsKeyMessage = KeyProtoHandler::kIsMessage; - static const bool kIsValueMessage = ValueProtoHandler::kIsMessage; - typedef typename MapIf<kIsKeyMessage, Key, KeyProtoHandlerCppType>::type + static const bool kIsKeyMessage = KeyWireHandler::kIsMessage; + static const bool kIsValueMessage = ValueWireHandler::kIsMessage; + typedef typename KeyWireHandler::CppType KeyInternalType; + typedef typename ValueWireHandler::CppType ValueInternalType; + typedef typename MapIf<kIsKeyMessage, Key, KeyInternalType>::type KeyCppType; - typedef typename MapIf<kIsValueMessage, Value, ValueProtoHandlerCppType>::type + typedef typename MapIf<kIsValueMessage, Value, ValueInternalType>::type ValCppType; - // Handlers for key/value's internal stored type. Provide utilities to - // manipulate internal stored type. We need it because some types are stored - // as values and others are stored as pointers (Message and string), but we - // need to keep the code in MapEntry unified instead of providing different - // codes for each type. - typedef MapCppTypeHandler<KeyCppType> KeyCppHandler; - typedef MapCppTypeHandler<ValCppType> ValueCppHandler; - - // Define internal memory layout. Strings and messages are stored as - // pointers, while other types are stored as values. - static const bool kKeyIsStringOrMessage = KeyCppHandler::kIsStringOrMessage; - static const bool kValIsStringOrMessage = ValueCppHandler::kIsStringOrMessage; - typedef typename MapIf<kKeyIsStringOrMessage, KeyCppType*, KeyCppType>::type - KeyBase; - typedef typename MapIf<kValIsStringOrMessage, ValCppType*, ValCppType>::type - ValueBase; - // Abbreviation for MapEntry typedef typename google::protobuf::internal::MapEntry< - Key, Value, KeyProtoType, ValueProtoType, default_enum_value> EntryType; + Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> EntryType; - // Constants for field number. - static const int kKeyFieldNumber = 1; - static const int kValueFieldNumber = 2; - - // Constants for field tag. - static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( - kKeyFieldNumber, KeyProtoHandler::kWireType); - static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( - kValueFieldNumber, ValueProtoHandler::kWireType); - static const int kTagSize = 1; + // Abbreviation for MapEntryLite + typedef typename google::protobuf::internal::MapEntryLite< + Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> + EntryLiteType; public: ~MapEntry() { if (this == default_instance_) { delete reflection_; - } else { - KeyCppHandler::Delete(key_); - ValueCppHandler::Delete(value_); } } // accessors ====================================================== - inline void set_key(const KeyCppType& key) { - KeyCppHandler::EnsureMutable(&key_); - KeyCppHandler::Merge(key, &key_); - set_has_key(); - } virtual inline const KeyCppType& key() const { - return KeyCppHandler::Reference(key_); + return entry_lite_.key(); } inline KeyCppType* mutable_key() { - set_has_key(); - KeyCppHandler::EnsureMutable(&key_); - return KeyCppHandler::Pointer(key_); - } - inline void set_value(const ValCppType& value) { - ValueCppHandler::EnsureMutable(&value_); - ValueCppHandler::Merge(value, &value_); - set_has_value(); + return entry_lite_.mutable_key(); } virtual inline const ValCppType& value() const { - GOOGLE_CHECK(default_instance_ != NULL); - return ValueCppHandler::DefaultIfNotInitialized(value_, - default_instance_->value_); + return entry_lite_.value(); } inline ValCppType* mutable_value() { - set_has_value(); - ValueCppHandler::EnsureMutable(&value_); - return ValueCppHandler::Pointer(value_); + return entry_lite_.mutable_value(); } // implements Message ============================================= bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) { - uint32 tag; - - for (;;) { - // 1) corrupted data: return false; - // 2) unknown field: skip without putting into unknown field set; - // 3) unknown enum value: keep it in parsing. In proto2, caller should - // check the value and put this entry into containing message's unknown - // field set if the value is an unknown enum. In proto3, caller doesn't - // need to care whether the value is unknown enum; - // 4) missing key/value: missed key/value will have default value. caller - // should take this entry as if key/value is set to default value. - tag = input->ReadTag(); - switch (tag) { - case kKeyTag: - if (!KeyProtoHandler::Read(input, mutable_key())) return false; - set_has_key(); - if (!input->ExpectTag(kValueTag)) break; - GOOGLE_FALLTHROUGH_INTENDED; - - case kValueTag: - if (!ValueProtoHandler::Read(input, mutable_value())) return false; - set_has_value(); - if (input->ExpectAtEnd()) return true; - break; - - default: - if (tag == 0 || - WireFormatLite::GetTagWireType(tag) == - WireFormatLite::WIRETYPE_END_GROUP) { - return true; - } - if (!WireFormatLite::SkipField(input, tag)) return false; - break; - } - } + return entry_lite_.MergePartialFromCodedStream(input); } int ByteSize() const { - int size = 0; - size += has_key() ? kTagSize + KeyProtoHandler::ByteSize(key()) : 0; - size += has_value() ? kTagSize + ValueProtoHandler::ByteSize(value()) : 0; - return size; + return entry_lite_.ByteSize(); } void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const { - KeyProtoHandler::Write(kKeyFieldNumber, key(), output); - ValueProtoHandler::Write(kValueFieldNumber, value(), output); + entry_lite_.SerializeWithCachedSizes(output); } ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const { - output = KeyProtoHandler::WriteToArray(kKeyFieldNumber, key(), output); - output = - ValueProtoHandler::WriteToArray(kValueFieldNumber, value(), output); - return output; + return entry_lite_.SerializeWithCachedSizesToArray(output); } int GetCachedSize() const { - int size = 0; - size += has_key() ? kTagSize + KeyProtoHandler::GetCachedSize(key()) : 0; - size += - has_value() ? kTagSize + ValueProtoHandler::GetCachedSize(value()) : 0; - return size; + return entry_lite_.GetCachedSize(); } - bool IsInitialized() const { return ValueCppHandler::IsInitialized(value_); } + bool IsInitialized() const { + return entry_lite_.IsInitialized(); + } Message* New() const { MapEntry* entry = new MapEntry; entry->descriptor_ = descriptor_; entry->reflection_ = reflection_; - entry->default_instance_ = default_instance_; + entry->set_default_instance(default_instance_); + return entry; + } + + Message* New(Arena* arena) const { + MapEntry* entry = Arena::CreateMessage<MapEntry>(arena); + entry->descriptor_ = descriptor_; + entry->reflection_ = reflection_; + entry->set_default_instance(default_instance_); return entry; } int SpaceUsed() const { int size = sizeof(MapEntry); - size += KeyCppHandler::SpaceUsedInMapEntry(key_); - size += ValueCppHandler::SpaceUsedInMapEntry(value_); + size += entry_lite_.SpaceUsed(); return size; } @@ -275,30 +214,19 @@ class LIBPROTOBUF_EXPORT MapEntry : public MapEntryBase { } void MergeFrom(const MapEntry& from) { - if (from._has_bits_[0]) { - if (from.has_key()) { - KeyCppHandler::EnsureMutable(&key_); - KeyCppHandler::Merge(from.key(), &key_); - set_has_key(); - } - if (from.has_value()) { - ValueCppHandler::EnsureMutable(&value_); - ValueCppHandler::Merge(from.value(), &value_); - set_has_value(); - } - } + entry_lite_.MergeFrom(from.entry_lite_); } void Clear() { - KeyCppHandler::Clear(&key_); - ValueCppHandler::ClearMaybeByDefaultEnum(&value_, default_enum_value); - clear_has_key(); - clear_has_value(); + entry_lite_.Clear(); } void InitAsDefaultInstance() { - KeyCppHandler::AssignDefaultValue(&key_); - ValueCppHandler::AssignDefaultValue(&value_); + entry_lite_.InitAsDefaultInstance(); + } + + Arena* GetArena() const { + return entry_lite_.GetArena(); } // Create default MapEntry instance for given descriptor. Descriptor has to be @@ -306,140 +234,58 @@ class LIBPROTOBUF_EXPORT MapEntry : public MapEntryBase { // may have the same type and MapEntry class. The given descriptor is needed // to distinguish instances of the same MapEntry class. static MapEntry* CreateDefaultInstance(const Descriptor* descriptor) { - MapEntry* entry = new MapEntry(); + MapEntry* entry = new MapEntry; const Reflection* reflection = new GeneratedMessageReflection( descriptor, entry, offsets_, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _has_bits_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_._has_bits_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _unknown_fields_), -1, DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(MapEntry), -1); entry->descriptor_ = descriptor; entry->reflection_ = reflection; - entry->default_instance_ = entry; + entry->set_default_instance(entry); entry->InitAsDefaultInstance(); + RegisterMapEntryDefaultInstance(entry); return entry; } - // Create a MapEntry for given key and value from google::protobuf::Map in - // serialization. This function is only called when value is enum. Enum is - // treated differently because its type in MapEntry is int and its type in - // google::protobuf::Map is enum. We cannot create a reference to int from an enum. - static MapEntry* EnumWrap(const Key& key, const Value value) { - return new MapEnumEntryWrapper<Key, Value, KeyProtoType, ValueProtoType, - default_enum_value>(key, value); - } + private: + MapEntry() : default_instance_(NULL), entry_lite_() {} - // Like above, but for all the other types. This avoids value copy to create - // MapEntry from google::protobuf::Map in serialization. - static MapEntry* Wrap(const Key& key, const Value& value) { - return new MapEntryWrapper<Key, Value, KeyProtoType, ValueProtoType, - default_enum_value>(key, value); - } + explicit MapEntry(Arena* arena) + : default_instance_(NULL), entry_lite_(arena) {} - protected: - void set_has_key() { _has_bits_[0] |= 0x00000001u; } - bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void clear_has_key() { _has_bits_[0] &= ~0x00000001u; } - void set_has_value() { _has_bits_[0] |= 0x00000002u; } - bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; } - void clear_has_value() { _has_bits_[0] &= ~0x00000002u; } + inline Arena* GetArenaNoVirtual() const { + return entry_lite_.GetArenaNoVirtual(); + } - private: - // Serializing a generated message containing map field involves serializing - // key-value pairs from google::protobuf::Map. The wire format of each key-value pair - // after serialization should be the same as that of a MapEntry message - // containing the same key and value inside it. However, google::protobuf::Map doesn't - // store key and value as MapEntry message, which disables us to use existing - // code to serialize message. In order to use existing code to serialize - // message, we need to construct a MapEntry from key-value pair. But it - // involves copy of key and value to construct a MapEntry. In order to avoid - // this copy in constructing a MapEntry, we need the following class which - // only takes references of given key and value. - template <typename KeyNested, typename ValueNested, - FieldDescriptor::Type KeyProtoNested, - FieldDescriptor::Type ValueProtoNested, int default_enum> - class LIBPROTOBUF_EXPORT MapEntryWrapper - : public MapEntry<KeyNested, ValueNested, KeyProtoNested, - ValueProtoNested, default_enum> { - typedef MapEntry<KeyNested, ValueNested, KeyProtoNested, ValueProtoNested, - default_enum_value> Base; - typedef typename Base::KeyCppType KeyCppType; - typedef typename Base::ValCppType ValCppType; - - public: - MapEntryWrapper(const KeyNested& key, const ValueNested& value) - : key_(key), value_(value) { - Base::set_has_key(); - Base::set_has_value(); - } - inline const KeyCppType& key() const { return key_; } - inline const ValCppType& value() const { return value_; } - - private: - const Key& key_; - const Value& value_; - }; - - // Like above, but for enum value only, which stores value instead of - // reference of value field inside. This is needed because the type of value - // field in constructor is an enum, while we need to store it as an int. If we - // initialize a reference to int with a reference to enum, compiler will - // generate a temporary int from enum and initialize the reference to int with - // the temporary. - template <typename KeyNested, typename ValueNested, - FieldDescriptor::Type KeyProtoNested, - FieldDescriptor::Type ValueProtoNested, int default_enum> - class LIBPROTOBUF_EXPORT MapEnumEntryWrapper - : public MapEntry<KeyNested, ValueNested, KeyProtoNested, - ValueProtoNested, default_enum> { - typedef MapEntry<KeyNested, ValueNested, KeyProtoNested, ValueProtoNested, - default_enum> Base; - typedef typename Base::KeyCppType KeyCppType; - typedef typename Base::ValCppType ValCppType; - - public: - MapEnumEntryWrapper(const KeyNested& key, const ValueNested& value) - : key_(key), value_(value) { - Base::set_has_key(); - Base::set_has_value(); - } - inline const KeyCppType& key() const { return key_; } - inline const ValCppType& value() const { return value_; } - - private: - const KeyCppType& key_; - const ValCppType value_; - }; - - MapEntry() : default_instance_(NULL) { - KeyCppHandler::Initialize(&key_); - ValueCppHandler::InitializeMaybeByDefaultEnum(&value_, default_enum_value); - _has_bits_[0] = 0; + void set_default_instance(MapEntry* default_instance) { + default_instance_ = default_instance; + entry_lite_.set_default_instance(&default_instance->entry_lite_); } - KeyBase key_; - ValueBase value_; static int offsets_[2]; UnknownFieldSet _unknown_fields_; - uint32 _has_bits_[1]; MapEntry* default_instance_; + EntryLiteType entry_lite_; friend class ::google::protobuf::Arena; - template <typename K, typename V, - FieldDescriptor::Type KType, - FieldDescriptor::Type VType, int default_enum> + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + template <typename K, typename V, WireFormatLite::FieldType k_wire_type, + WireFormatLite::FieldType, int default_enum> friend class LIBPROTOBUF_EXPORT internal::MapField; friend class LIBPROTOBUF_EXPORT internal::GeneratedMessageReflection; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry); }; -template <typename Key, typename Value, FieldDescriptor::Type KeyProtoType, - FieldDescriptor::Type ValueProtoType, int default_enum_value> -int MapEntry<Key, Value, KeyProtoType, ValueProtoType, +template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, int default_enum_value> +int MapEntry<Key, Value, kKeyFieldType, kValueFieldType, default_enum_value>::offsets_[2] = { - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, key_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, value_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.key_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.value_), }; } // namespace internal diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h new file mode 100644 index 00000000..304fba88 --- /dev/null +++ b/src/google/protobuf/map_entry_lite.h @@ -0,0 +1,409 @@ +// 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_MAP_ENTRY_LITE_H__ +#define GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__ + +#include <google/protobuf/map_type_handler.h> +#include <google/protobuf/wire_format_lite_inl.h> + +namespace google { +namespace protobuf { +class Arena; +namespace internal { +template <typename Key, typename Value, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> +class MapEntry; +template <typename Key, typename Value, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> +class MapFieldLite; +} // namespace internal +} // namespace protobuf + +namespace protobuf { +namespace internal { + +// MapEntryLite is used to implement parsing and serialization of map for lite +// runtime. +template <typename Key, typename Value, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> +class LIBPROTOBUF_EXPORT MapEntryLite : public MessageLite { + // Handlers for key/value wire type. Provide utilities to parse/serialize + // key/value. + typedef MapWireFieldTypeHandler<kKeyFieldType> KeyWireHandler; + typedef MapWireFieldTypeHandler<kValueFieldType> ValueWireHandler; + + // Define key/value's internal stored type. Message is the only one whose + // internal stored type cannot be inferred from its proto type + static const bool kIsKeyMessage = KeyWireHandler::kIsMessage; + static const bool kIsValueMessage = ValueWireHandler::kIsMessage; + typedef typename KeyWireHandler::CppType KeyInternalType; + typedef typename ValueWireHandler::CppType ValueInternalType; + typedef typename MapIf<kIsKeyMessage, Key, KeyInternalType>::type + KeyCppType; + typedef typename MapIf<kIsValueMessage, Value, ValueInternalType>::type + ValCppType; + + // Handlers for key/value's internal stored type. Provide utilities to + // manipulate internal stored type. We need it because some types are stored + // as values and others are stored as pointers (Message and string), but we + // need to keep the code in MapEntry unified instead of providing different + // codes for each type. + typedef MapCppTypeHandler<KeyCppType> KeyCppHandler; + typedef MapCppTypeHandler<ValCppType> ValueCppHandler; + + // Define internal memory layout. Strings and messages are stored as + // pointers, while other types are stored as values. + static const bool kKeyIsStringOrMessage = KeyCppHandler::kIsStringOrMessage; + static const bool kValIsStringOrMessage = ValueCppHandler::kIsStringOrMessage; + typedef typename MapIf<kKeyIsStringOrMessage, KeyCppType*, KeyCppType>::type + KeyBase; + typedef typename MapIf<kValIsStringOrMessage, ValCppType*, ValCppType>::type + ValueBase; + + // Constants for field number. + static const int kKeyFieldNumber = 1; + static const int kValueFieldNumber = 2; + + // Constants for field tag. + static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( + kKeyFieldNumber, KeyWireHandler::kWireType); + static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( + kValueFieldNumber, ValueWireHandler::kWireType); + static const int kTagSize = 1; + + public: + ~MapEntryLite() { + if (this != default_instance_) { + KeyCppHandler::Delete(key_); + ValueCppHandler::Delete(value_); + } + } + + // accessors ====================================================== + + virtual inline const KeyCppType& key() const { + return KeyCppHandler::Reference(key_); + } + inline KeyCppType* mutable_key() { + set_has_key(); + KeyCppHandler::EnsureMutable(&key_, GetArenaNoVirtual()); + return KeyCppHandler::Pointer(key_); + } + virtual inline const ValCppType& value() const { + GOOGLE_CHECK(default_instance_ != NULL); + return ValueCppHandler::DefaultIfNotInitialized(value_, + default_instance_->value_); + } + inline ValCppType* mutable_value() { + set_has_value(); + ValueCppHandler::EnsureMutable(&value_, GetArenaNoVirtual()); + return ValueCppHandler::Pointer(value_); + } + + // implements MessageLite ========================================= + + // MapEntryLite is for implementation only and this function isn't called + // anywhere. Just provide a fake implementation here for MessageLite. + string GetTypeName() const { return ""; } + + void CheckTypeAndMergeFrom(const MessageLite& other) { + MergeFrom(*::google::protobuf::down_cast<const MapEntryLite*>(&other)); + } + + bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) { + uint32 tag; + + for (;;) { + // 1) corrupted data: return false; + // 2) unknown field: skip without putting into unknown field set; + // 3) unknown enum value: keep it in parsing. In proto2, caller should + // check the value and put this entry into containing message's unknown + // field set if the value is an unknown enum. In proto3, caller doesn't + // need to care whether the value is unknown enum; + // 4) missing key/value: missed key/value will have default value. caller + // should take this entry as if key/value is set to default value. + tag = input->ReadTag(); + switch (tag) { + case kKeyTag: + if (!KeyWireHandler::Read(input, mutable_key())) return false; + set_has_key(); + if (!input->ExpectTag(kValueTag)) break; + GOOGLE_FALLTHROUGH_INTENDED; + + case kValueTag: + if (!ValueWireHandler::Read(input, mutable_value())) return false; + set_has_value(); + if (input->ExpectAtEnd()) return true; + break; + + default: + if (tag == 0 || + WireFormatLite::GetTagWireType(tag) == + WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + if (!WireFormatLite::SkipField(input, tag)) return false; + break; + } + } + } + + int ByteSize() const { + int size = 0; + size += has_key() ? kTagSize + KeyWireHandler::ByteSize(key()) : 0; + size += has_value() ? kTagSize + ValueWireHandler::ByteSize(value()) : 0; + return size; + } + + void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const { + KeyWireHandler::Write(kKeyFieldNumber, key(), output); + ValueWireHandler::Write(kValueFieldNumber, value(), output); + } + + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const { + output = KeyWireHandler::WriteToArray(kKeyFieldNumber, key(), output); + output = + ValueWireHandler::WriteToArray(kValueFieldNumber, value(), output); + return output; + } + + int GetCachedSize() const { + int size = 0; + size += has_key() ? kTagSize + KeyWireHandler::GetCachedSize(key()) : 0; + size += + has_value() ? kTagSize + ValueWireHandler::GetCachedSize(value()) : 0; + return size; + } + + bool IsInitialized() const { return ValueCppHandler::IsInitialized(value_); } + + MessageLite* New() const { + MapEntryLite* entry = new MapEntryLite; + entry->default_instance_ = default_instance_; + return entry; + } + + MessageLite* New(Arena* arena) const { + MapEntryLite* entry = Arena::CreateMessage<MapEntryLite>(arena); + entry->default_instance_ = default_instance_; + return entry; + } + + int SpaceUsed() const { + int size = sizeof(MapEntryLite); + size += KeyCppHandler::SpaceUsedInMapEntry(key_); + size += ValueCppHandler::SpaceUsedInMapEntry(value_); + return size; + } + + void MergeFrom(const MapEntryLite& from) { + if (from._has_bits_[0]) { + if (from.has_key()) { + KeyCppHandler::EnsureMutable(&key_, GetArenaNoVirtual()); + KeyCppHandler::Merge(from.key(), &key_); + set_has_key(); + } + if (from.has_value()) { + ValueCppHandler::EnsureMutable(&value_, GetArenaNoVirtual()); + ValueCppHandler::Merge(from.value(), &value_); + set_has_value(); + } + } + } + + void Clear() { + KeyCppHandler::Clear(&key_); + ValueCppHandler::ClearMaybeByDefaultEnum(&value_, default_enum_value); + clear_has_key(); + clear_has_value(); + } + + void InitAsDefaultInstance() { + KeyCppHandler::AssignDefaultValue(&key_); + ValueCppHandler::AssignDefaultValue(&value_); + } + + Arena* GetArena() const { + return GetArenaNoVirtual(); + } + + // Create a MapEntryLite for given key and value from google::protobuf::Map in + // serialization. This function is only called when value is enum. Enum is + // treated differently because its type in MapEntry is int and its type in + // google::protobuf::Map is enum. We cannot create a reference to int from an enum. + static MapEntryLite* EnumWrap(const Key& key, const Value value, + Arena* arena) { + return Arena::Create<MapEnumEntryWrapper< + Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> >( + arena, key, value, arena); + } + + // Like above, but for all the other types. This avoids value copy to create + // MapEntryLite from google::protobuf::Map in serialization. + static MapEntryLite* Wrap(const Key& key, const Value& value, Arena* arena) { + return Arena::Create<MapEntryWrapper<Key, Value, kKeyFieldType, + kValueFieldType, default_enum_value> >( + arena, key, value, arena); + } + + protected: + void set_has_key() { _has_bits_[0] |= 0x00000001u; } + bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; } + void clear_has_key() { _has_bits_[0] &= ~0x00000001u; } + void set_has_value() { _has_bits_[0] |= 0x00000002u; } + bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; } + void clear_has_value() { _has_bits_[0] &= ~0x00000002u; } + + private: + // Serializing a generated message containing map field involves serializing + // key-value pairs from google::protobuf::Map. The wire format of each key-value pair + // after serialization should be the same as that of a MapEntry message + // containing the same key and value inside it. However, google::protobuf::Map doesn't + // store key and value as MapEntry message, which disables us to use existing + // code to serialize message. In order to use existing code to serialize + // message, we need to construct a MapEntry from key-value pair. But it + // involves copy of key and value to construct a MapEntry. In order to avoid + // this copy in constructing a MapEntry, we need the following class which + // only takes references of given key and value. + template <typename K, typename V, WireFormatLite::FieldType k_wire_type, + WireFormatLite::FieldType v_wire_type, int default_enum> + class LIBPROTOBUF_EXPORT MapEntryWrapper + : public MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> { + typedef MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> Base; + typedef typename Base::KeyCppType KeyCppType; + typedef typename Base::ValCppType ValCppType; + + public: + MapEntryWrapper(const K& key, const V& value, Arena* arena) + : MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum>(arena), + key_(key), + value_(value) { + Base::set_has_key(); + Base::set_has_value(); + } + inline const KeyCppType& key() const { return key_; } + inline const ValCppType& value() const { return value_; } + + private: + const Key& key_; + const Value& value_; + + friend class ::google::protobuf::Arena; + typedef void DestructorSkippable_; + }; + + // Like above, but for enum value only, which stores value instead of + // reference of value field inside. This is needed because the type of value + // field in constructor is an enum, while we need to store it as an int. If we + // initialize a reference to int with a reference to enum, compiler will + // generate a temporary int from enum and initialize the reference to int with + // the temporary. + template <typename K, typename V, WireFormatLite::FieldType k_wire_type, + WireFormatLite::FieldType v_wire_type, int default_enum> + class LIBPROTOBUF_EXPORT MapEnumEntryWrapper + : public MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> { + typedef MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> Base; + typedef typename Base::KeyCppType KeyCppType; + typedef typename Base::ValCppType ValCppType; + + public: + MapEnumEntryWrapper(const K& key, const V& value, Arena* arena) + : MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum>(arena), + key_(key), + value_(value) { + Base::set_has_key(); + Base::set_has_value(); + } + inline const KeyCppType& key() const { return key_; } + inline const ValCppType& value() const { return value_; } + + private: + const KeyCppType& key_; + const ValCppType value_; + + friend class ::google::protobuf::Arena; + typedef void DestructorSkippable_; + }; + + MapEntryLite() : default_instance_(NULL), arena_(NULL) { + KeyCppHandler::Initialize(&key_, NULL); + ValueCppHandler::InitializeMaybeByDefaultEnum( + &value_, default_enum_value, NULL); + _has_bits_[0] = 0; + } + + explicit MapEntryLite(Arena* arena) + : default_instance_(NULL), arena_(arena) { + KeyCppHandler::Initialize(&key_, arena); + ValueCppHandler::InitializeMaybeByDefaultEnum( + &value_, default_enum_value, arena); + _has_bits_[0] = 0; + } + + inline Arena* GetArenaNoVirtual() const { + return arena_; + } + + void set_default_instance(MapEntryLite* default_instance) { + default_instance_ = default_instance; + } + + MapEntryLite* default_instance_; + + KeyBase key_; + ValueBase value_; + Arena* arena_; + uint32 _has_bits_[1]; + + friend class ::google::protobuf::Arena; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + template <typename K, typename V, WireFormatLite::FieldType, + WireFormatLite::FieldType, int> + friend class LIBPROTOBUF_EXPORT internal::MapEntry; + template <typename K, typename V, WireFormatLite::FieldType, + WireFormatLite::FieldType, int> + friend class LIBPROTOBUF_EXPORT internal::MapFieldLite; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite); +}; + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__ diff --git a/src/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc index 74431628..fd40c0d8 100644 --- a/src/google/protobuf/map_field.cc +++ b/src/google/protobuf/map_field.cc @@ -30,12 +30,39 @@ #include <google/protobuf/map_field.h> +#include <vector> + namespace google { namespace protobuf { namespace internal { +ProtobufOnceType map_entry_default_instances_once_; +Mutex* map_entry_default_instances_mutex_; +vector<MessageLite*>* map_entry_default_instances_; + +void DeleteMapEntryDefaultInstances() { + for (int i = 0; i < map_entry_default_instances_->size(); ++i) { + delete map_entry_default_instances_->at(i); + } + delete map_entry_default_instances_mutex_; + delete map_entry_default_instances_; +} + +void InitMapEntryDefaultInstances() { + map_entry_default_instances_mutex_ = new Mutex(); + map_entry_default_instances_ = new vector<MessageLite*>(); + OnShutdown(&DeleteMapEntryDefaultInstances); +} + +void RegisterMapEntryDefaultInstance(MessageLite* default_instance) { + ::google::protobuf::GoogleOnceInit(&map_entry_default_instances_once_, + &InitMapEntryDefaultInstances); + MutexLock lock(map_entry_default_instances_mutex_); + map_entry_default_instances_->push_back(default_instance); +} + MapFieldBase::~MapFieldBase() { - if (repeated_field_ != NULL) delete repeated_field_; + if (repeated_field_ != NULL && arena_ == NULL) delete repeated_field_; } const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const { @@ -91,7 +118,9 @@ void MapFieldBase::SyncRepeatedFieldWithMap() const { } void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const { - if (repeated_field_ == NULL) repeated_field_ = new RepeatedPtrField<Message>; + if (repeated_field_ == NULL) { + repeated_field_ = Arena::Create<RepeatedPtrField<Message> >(arena_, arena_); + } } void MapFieldBase::SyncMapWithRepeatedField() const { diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h index 4ceaf4a0..6d8b6ec8 100644 --- a/src/google/protobuf/map_field.h +++ b/src/google/protobuf/map_field.h @@ -34,8 +34,10 @@ #include <google/protobuf/stubs/atomicops.h> #include <google/protobuf/stubs/common.h> #include <google/protobuf/generated_message_reflection.h> -#include <google/protobuf/map.h> +#include <google/protobuf/arena.h> #include <google/protobuf/map_entry.h> +#include <google/protobuf/map_field_lite.h> +#include <google/protobuf/map_type_handler.h> #include <google/protobuf/message.h> #include <google/protobuf/repeated_field.h> #include <google/protobuf/unknown_field_set.h> @@ -56,7 +58,13 @@ class MapFieldAccessor; class LIBPROTOBUF_EXPORT MapFieldBase { public: MapFieldBase() - : base_map_(NULL), + : arena_(NULL), + repeated_field_(NULL), + entry_descriptor_(NULL), + assign_descriptor_callback_(NULL), + state_(STATE_MODIFIED_MAP) {} + explicit MapFieldBase(Arena* arena) + : arena_(arena), repeated_field_(NULL), entry_descriptor_(NULL), assign_descriptor_callback_(NULL), @@ -109,7 +117,7 @@ class LIBPROTOBUF_EXPORT MapFieldBase { CLEAN = 2, // data in map and repeated field are same }; - mutable void* base_map_; + Arena* arena_; mutable RepeatedPtrField<Message>* repeated_field_; // MapEntry can only be created from MapField. To create MapEntry, MapField // needs to know its descriptor, because MapEntry is not generated class which @@ -134,41 +142,55 @@ class LIBPROTOBUF_EXPORT MapFieldBase { // This class provides accesss to map field using generated api. It is used for // internal generated message implentation only. Users should never use this // directly. -template<typename Key, typename T, - FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value = 0> -class LIBPROTOBUF_EXPORT MapField : public MapFieldBase { - // Handlers for key/value's proto field type. - typedef MapProtoTypeHandler<KeyProto> KeyProtoHandler; - typedef MapProtoTypeHandler<ValueProto> ValueProtoHandler; +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value = 0> +class LIBPROTOBUF_EXPORT MapField : public MapFieldBase, + public MapFieldLite<Key, T, kKeyFieldType, kValueFieldType, + default_enum_value> { + // Handlers for key/value wire type. Provide utilities to parse/serialize + // key/value. + typedef MapWireFieldTypeHandler<kKeyFieldType> KeyWireHandler; + typedef MapWireFieldTypeHandler<kValueFieldType> ValueWireHandler; // Define key/value's internal stored type. - typedef typename KeyProtoHandler::CppType KeyHandlerCpp; - typedef typename ValueProtoHandler::CppType ValHandlerCpp; - static const bool kIsKeyMessage = KeyProtoHandler::kIsMessage; - static const bool kIsValMessage = ValueProtoHandler::kIsMessage; - typedef typename MapIf<kIsKeyMessage, Key, KeyHandlerCpp>::type KeyCpp; - typedef typename MapIf<kIsValMessage, T , ValHandlerCpp>::type ValCpp; + static const bool kIsKeyMessage = KeyWireHandler::kIsMessage; + static const bool kIsValMessage = ValueWireHandler::kIsMessage; + typedef typename KeyWireHandler::CppType KeyInternalType; + typedef typename ValueWireHandler::CppType ValueInternalType; + typedef typename MapIf<kIsKeyMessage, Key, KeyInternalType>::type KeyCpp; + typedef typename MapIf<kIsValMessage, T , ValueInternalType>::type ValCpp; // Handlers for key/value's internal stored type. typedef MapCppTypeHandler<KeyCpp> KeyHandler; typedef MapCppTypeHandler<ValCpp> ValHandler; // Define message type for internal repeated field. - typedef MapEntry<Key, T, KeyProto, ValueProto, default_enum_value> EntryType; + typedef MapEntry<Key, T, kKeyFieldType, kValueFieldType, default_enum_value> + EntryType; + typedef MapEntryLite<Key, T, kKeyFieldType, kValueFieldType, + default_enum_value> EntryLiteType; + + // Define abbreviation for parent MapFieldLite + typedef MapFieldLite<Key, T, kKeyFieldType, kValueFieldType, + default_enum_value> MapFieldLiteType; // Enum needs to be handled differently from other types because it has // different exposed type in google::protobuf::Map's api and repeated field's api. For // details see the comment in the implementation of // SyncMapWithRepeatedFieldNoLocki. - static const bool kIsValueEnum = ValueProtoHandler::kIsEnum; + static const bool kIsValueEnum = ValueWireHandler::kIsEnum; typedef typename MapIf<kIsValueEnum, T, const T&>::type CastValueType; public: MapField(); + explicit MapField(Arena* arena); // MapField doesn't own the default_entry, which means default_entry must // outlive the lifetime of MapField. MapField(const Message* default_entry); + // For tests only. + MapField(Arena* arena, const Message* default_entry); ~MapField(); // Accessors @@ -178,29 +200,22 @@ class LIBPROTOBUF_EXPORT MapField : public MapFieldBase { // Convenient methods for generated message implementation. int size() const; void Clear(); - void MergeFrom(const MapField& other); - void Swap(MapField* other); + void MergeFrom(const MapFieldLiteType& other); + void Swap(MapFieldLiteType* other); // Allocates metadata only if this MapField is part of a generated message. void SetEntryDescriptor(const Descriptor** descriptor); void SetAssignDescriptorCallback(void (*callback)()); - // Set default enum value only for proto2 map field whose value is enum type. - void SetDefaultEnumValue(); - - // Used in the implementation of parsing. Caller should take the ownership. - EntryType* NewEntry() const; - // Used in the implementation of serializing enum value type. Caller should - // take the ownership. - EntryType* NewEnumEntryWrapper(const Key& key, const T t) const; - // Used in the implementation of serializing other value types. Caller should - // take the ownership. - EntryType* NewEntryWrapper(const Key& key, const T& t) const; - private: + typedef void DestructorSkippable_; + // MapField needs MapEntry's default instance to create new MapEntry. void InitDefaultEntryOnce() const; + // Manually set default entry instance. For test only. + void SetDefaultEntryOnce(const EntryType* default_entry) const; + // Convenient methods to get internal google::protobuf::Map const Map<Key, T>& GetInternalMap() const; Map<Key, T>* MutableInternalMap(); @@ -211,6 +226,8 @@ class LIBPROTOBUF_EXPORT MapField : public MapFieldBase { int SpaceUsedExcludingSelfNoLock() const; mutable const EntryType* default_entry_; + + friend class ::google::protobuf::Arena; }; } // namespace internal diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h index 6f17df95..ae63c721 100644 --- a/src/google/protobuf/map_field_inl.h +++ b/src/google/protobuf/map_field_inl.h @@ -43,160 +43,183 @@ namespace google { namespace protobuf { namespace internal { -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> -MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MapField() - : default_entry_(NULL) { - MapFieldBase::base_map_ = new Map<Key, T>; - SetDefaultEnumValue(); -} +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> +MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField() + : default_entry_(NULL) {} + +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> +MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField( + Arena* arena) + : MapFieldBase(arena), + MapFieldLite<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>( + arena), + default_entry_(NULL) {} -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> -MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MapField( +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> +MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField( const Message* default_entry) - : default_entry_(down_cast<const EntryType*>(default_entry)) { - MapFieldBase::base_map_ = new Map<Key, T>; - SetDefaultEnumValue(); -} + : default_entry_(down_cast<const EntryType*>(default_entry)) {} -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> -MapField<Key, T, KeyProto, ValueProto, default_enum_value>::~MapField() { - delete reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_); -} +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> +MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField( + Arena* arena, const Message* default_entry) + : MapFieldBase(arena), + MapFieldLite<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>( + arena), + default_entry_(down_cast<const EntryType*>(default_entry)) {} + +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> +MapField<Key, T, kKeyFieldType, kValueFieldType, + default_enum_value>::~MapField() {} -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> -int MapField<Key, T, KeyProto, ValueProto, default_enum_value>::size() const { +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> +int +MapField<Key, T, kKeyFieldType, kValueFieldType, + default_enum_value>::size() const { SyncMapWithRepeatedField(); - return GetInternalMap().size(); + return MapFieldLiteType::GetInternalMap().size(); } -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> -void MapField<Key, T, KeyProto, ValueProto, default_enum_value>::Clear() { +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> +void +MapField<Key, T, kKeyFieldType, kValueFieldType, + default_enum_value>::Clear() { SyncMapWithRepeatedField(); - MutableInternalMap()->clear(); + MapFieldLiteType::MutableInternalMap()->clear(); SetMapDirty(); } -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> const Map<Key, T>& -MapField<Key, T, KeyProto, ValueProto, default_enum_value>::GetMap() const { +MapField<Key, T, kKeyFieldType, kValueFieldType, + default_enum_value>::GetMap() const { SyncMapWithRepeatedField(); - return GetInternalMap(); + return MapFieldLiteType::GetInternalMap(); } -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> Map<Key, T>* -MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MutableMap() { +MapField<Key, T, kKeyFieldType, kValueFieldType, + default_enum_value>::MutableMap() { SyncMapWithRepeatedField(); - Map<Key, T>* result = MutableInternalMap(); + Map<Key, T>* result = MapFieldLiteType::MutableInternalMap(); SetMapDirty(); return result; } -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> -void MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MergeFrom( - const MapField& other) { +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> +void +MapField<Key, T, kKeyFieldType, kValueFieldType, + default_enum_value>::MergeFrom( + const MapFieldLiteType& other) { + const MapField& down_other = down_cast<const MapField&>(other); SyncMapWithRepeatedField(); - other.SyncMapWithRepeatedField(); - - Map<Key, T>* map = MutableInternalMap(); - const Map<Key, T>& other_map = other.GetInternalMap(); - for (typename Map<Key, T>::const_iterator it = other_map.begin(); - it != other_map.end(); ++it) { - (*map)[it->first] = it->second; - } + down_other.SyncMapWithRepeatedField(); + MapFieldLiteType::MergeFrom(other); SetMapDirty(); } -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> -void MapField<Key, T, KeyProto, ValueProto, default_enum_value>::Swap( - MapField* other) { - std::swap(repeated_field_, other->repeated_field_); - std::swap(base_map_, other->base_map_); - std::swap(state_, other->state_); +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> +void +MapField<Key, T, kKeyFieldType, kValueFieldType, + default_enum_value>::Swap( + MapFieldLiteType* other) { + MapField* down_other = down_cast<MapField*>(other); + std::swap(repeated_field_, down_other->repeated_field_); + MapFieldLiteType::Swap(other); + std::swap(state_, down_other->state_); } -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> void -MapField<Key, T, KeyProto, ValueProto, default_enum_value>::SetEntryDescriptor( +MapField<Key, T, kKeyFieldType, kValueFieldType, + default_enum_value>::SetEntryDescriptor( const Descriptor** descriptor) { entry_descriptor_ = descriptor; } -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> void -MapField<Key, T, KeyProto, ValueProto, +MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::SetAssignDescriptorCallback(void (*callback)()) { assign_descriptor_callback_ = callback; } -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> -void MapField<Key, T, KeyProto, ValueProto, - default_enum_value>::SetDefaultEnumValue() { - MutableInternalMap()->SetDefaultEnumValue(default_enum_value); -} - -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> -MapEntry<Key, T, KeyProto, ValueProto, default_enum_value>* -MapField<Key, T, KeyProto, ValueProto, default_enum_value>::NewEntry() const { - // The MapEntry instance created here is only used in generated code for - // parsing. It doesn't have default instance, descriptor or reflection, - // because these are not needed in parsing and will prevent us from using it - // for parsing MessageLite. - return new EntryType(); -} - -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> -MapEntry<Key, T, KeyProto, ValueProto, default_enum_value>* -MapField<Key, T, KeyProto, ValueProto, default_enum_value>::NewEntryWrapper( - const Key& key, const T& t) const { - return EntryType::Wrap(key, t); -} - -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> -MapEntry<Key, T, KeyProto, ValueProto, default_enum_value>* -MapField<Key, T, KeyProto, ValueProto, default_enum_value>::NewEnumEntryWrapper( - const Key& key, const T t) const { - return EntryType::EnumWrap(key, t); -} - -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> -const Map<Key, T>& MapField<Key, T, KeyProto, ValueProto, - default_enum_value>::GetInternalMap() const { - return *reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_); +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> +const Map<Key, T>& +MapField<Key, T, kKeyFieldType, kValueFieldType, + default_enum_value>::GetInternalMap() const { + return MapFieldLiteType::GetInternalMap(); } -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> -Map<Key, T>* MapField<Key, T, KeyProto, ValueProto, - default_enum_value>::MutableInternalMap() { - return reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_); +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> +Map<Key, T>* +MapField<Key, T, kKeyFieldType, kValueFieldType, + default_enum_value>::MutableInternalMap() { + return MapFieldLiteType::MutableInternalMap(); } -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> -void MapField<Key, T, KeyProto, ValueProto, - default_enum_value>::SyncRepeatedFieldWithMapNoLock() const { +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> +void +MapField<Key, T, kKeyFieldType, kValueFieldType, + default_enum_value>::SyncRepeatedFieldWithMapNoLock() const { if (repeated_field_ == NULL) { - repeated_field_ = new RepeatedPtrField<Message>(); + if (arena_ == NULL) { + repeated_field_ = new RepeatedPtrField<Message>(); + } else { + repeated_field_ = + Arena::Create<RepeatedPtrField<Message> >(arena_, arena_); + } } - const Map<Key, T>& map = - *static_cast<const Map<Key, T>*>(MapFieldBase::base_map_); + const Map<Key, T>& map = GetInternalMap(); RepeatedPtrField<EntryType>* repeated_field = reinterpret_cast<RepeatedPtrField<EntryType>*>(repeated_field_); @@ -206,18 +229,21 @@ void MapField<Key, T, KeyProto, ValueProto, it != map.end(); ++it) { InitDefaultEntryOnce(); GOOGLE_CHECK(default_entry_ != NULL); - EntryType* new_entry = down_cast<EntryType*>(default_entry_->New()); + EntryType* new_entry = down_cast<EntryType*>(default_entry_->New(arena_)); repeated_field->AddAllocated(new_entry); - new_entry->set_key(it->first); - new_entry->set_value(it->second); + (*new_entry->mutable_key()) = it->first; + (*new_entry->mutable_value()) = it->second; } } -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> -void MapField<Key, T, KeyProto, ValueProto, - default_enum_value>::SyncMapWithRepeatedFieldNoLock() const { - Map<Key, T>* map = reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_); +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> +void +MapField<Key, T, kKeyFieldType, kValueFieldType, + default_enum_value>::SyncMapWithRepeatedFieldNoLock() const { + Map<Key, T>* map = const_cast<MapField*>(this)->MutableInternalMap(); RepeatedPtrField<EntryType>* repeated_field = reinterpret_cast<RepeatedPtrField<EntryType>*>(repeated_field_); map->clear(); @@ -232,15 +258,18 @@ void MapField<Key, T, KeyProto, ValueProto, } } -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> -int MapField<Key, T, KeyProto, ValueProto, - default_enum_value>::SpaceUsedExcludingSelfNoLock() const { +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> +int +MapField<Key, T, kKeyFieldType, kValueFieldType, + default_enum_value>::SpaceUsedExcludingSelfNoLock() const { int size = 0; if (repeated_field_ != NULL) { size += repeated_field_->SpaceUsedExcludingSelf(); } - Map<Key, T>* map = reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_); + Map<Key, T>* map = const_cast<MapField*>(this)->MutableInternalMap(); size += sizeof(*map); for (typename Map<Key, T>::iterator it = map->begin(); it != map->end(); ++it) { @@ -250,10 +279,14 @@ int MapField<Key, T, KeyProto, ValueProto, return size; } -template <typename Key, typename T, FieldDescriptor::Type KeyProto, - FieldDescriptor::Type ValueProto, int default_enum_value> -void MapField<Key, T, KeyProto, ValueProto, - default_enum_value>::InitDefaultEntryOnce() const { +template <typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType, + int default_enum_value> +void +MapField<Key, T, kKeyFieldType, kValueFieldType, + default_enum_value>::InitDefaultEntryOnce() + const { if (default_entry_ == NULL) { InitMetadataOnce(); GOOGLE_CHECK(*entry_descriptor_ != NULL); diff --git a/src/google/protobuf/map_field_lite.h b/src/google/protobuf/map_field_lite.h new file mode 100644 index 00000000..549ecc08 --- /dev/null +++ b/src/google/protobuf/map_field_lite.h @@ -0,0 +1,278 @@ +// 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_MAP_FIELD_LITE_H__ +#define GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__ + +#include <google/protobuf/map.h> +#include <google/protobuf/map_entry_lite.h> + +namespace google { +namespace protobuf { +namespace internal { + +// This class provides accesss to map field using generated api. It is used for +// internal generated message implentation only. Users should never use this +// directly. +template <typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type, + int default_enum_value = 0> +class LIBPROTOBUF_EXPORT MapFieldLite { + // Define message type for internal repeated field. + typedef MapEntryLite<Key, T, key_wire_type, value_wire_type, + default_enum_value> EntryType; + + public: + MapFieldLite(); + explicit MapFieldLite(Arena* arena); + virtual ~MapFieldLite(); + + // Accessors + virtual const Map<Key, T>& GetMap() const; + virtual Map<Key, T>* MutableMap(); + + // Convenient methods for generated message implementation. + virtual int size() const; + virtual void Clear(); + virtual void MergeFrom(const MapFieldLite& other); + virtual void Swap(MapFieldLite* other); + + // Set default enum value only for proto2 map field whose value is enum type. + void SetDefaultEnumValue(); + + // Used in the implementation of parsing. Caller should take the ownership. + EntryType* NewEntry() const; + // Used in the implementation of serializing enum value type. Caller should + // take the ownership. + EntryType* NewEnumEntryWrapper(const Key& key, const T t) const; + // Used in the implementation of serializing other value types. Caller should + // take the ownership. + EntryType* NewEntryWrapper(const Key& key, const T& t) const; + + protected: + // Convenient methods to get internal google::protobuf::Map + virtual const Map<Key, T>& GetInternalMap() const; + virtual Map<Key, T>* MutableInternalMap(); + + private: + typedef void DestructorSkippable_; + + Arena* arena_; + Map<Key, T>* map_; + + friend class ::google::protobuf::Arena; +}; + +template <typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type, + int default_enum_value> +MapFieldLite<Key, T, key_wire_type, value_wire_type, + default_enum_value>::MapFieldLite() + : arena_(NULL) { + map_ = new Map<Key, T>; + SetDefaultEnumValue(); +} + +template <typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type, + int default_enum_value> +MapFieldLite<Key, T, key_wire_type, value_wire_type, + default_enum_value>::MapFieldLite(Arena* arena) + : arena_(arena) { + map_ = Arena::Create<Map<Key, T> >(arena, arena); + SetDefaultEnumValue(); +} + +template <typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type, + int default_enum_value> +MapFieldLite<Key, T, key_wire_type, value_wire_type, + default_enum_value>::~MapFieldLite() { + delete map_; +} + +template <typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type, + int default_enum_value> +const Map<Key, T>& +MapFieldLite<Key, T, key_wire_type, value_wire_type, + default_enum_value>::GetMap() const { + return *map_; +} + +template <typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type, + int default_enum_value> +Map<Key, T>* +MapFieldLite<Key, T, key_wire_type, value_wire_type, + default_enum_value>::MutableMap() { + return map_; +} + +template <typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type, + int default_enum_value> +int +MapFieldLite<Key, T, key_wire_type, value_wire_type, + default_enum_value>::size() const { + return map_->size(); +} + +template <typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type, + int default_enum_value> +void +MapFieldLite<Key, T, key_wire_type, value_wire_type, + default_enum_value>::Clear() { + map_->clear(); +} + +template <typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type, + int default_enum_value> +void +MapFieldLite<Key, T, key_wire_type, value_wire_type, + default_enum_value>::MergeFrom( + const MapFieldLite& other) { + for (typename Map<Key, T>::const_iterator it = other.map_->begin(); + it != other.map_->end(); ++it) { + (*map_)[it->first] = it->second; + } +} + +template <typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type, + int default_enum_value> +void +MapFieldLite<Key, T, key_wire_type, value_wire_type, + default_enum_value>::Swap( + MapFieldLite* other) { + std::swap(map_, other->map_); +} + +template <typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type, + int default_enum_value> +void +MapFieldLite<Key, T, key_wire_type, value_wire_type, + default_enum_value>::SetDefaultEnumValue() { + MutableInternalMap()->SetDefaultEnumValue(default_enum_value); +} + +template <typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type, + int default_enum_value> +const Map<Key, T>& +MapFieldLite<Key, T, key_wire_type, value_wire_type, + default_enum_value>::GetInternalMap() const { + return *map_; +} + +template <typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type, + int default_enum_value> +Map<Key, T>* +MapFieldLite<Key, T, key_wire_type, value_wire_type, + default_enum_value>::MutableInternalMap() { + return map_; +} + +#define EntryType \ + MapEntryLite<Key, T, key_wire_type, value_wire_type, default_enum_value> + +template <typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type, + int default_enum_value> +EntryType* +MapFieldLite<Key, T, key_wire_type, value_wire_type, + default_enum_value>::NewEntry() const { + if (arena_ == NULL) { + return new EntryType(); + } else { + return Arena::CreateMessage<EntryType>(arena_); + } +} + +template <typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type, + int default_enum_value> +EntryType* +MapFieldLite<Key, T, key_wire_type, value_wire_type, + default_enum_value>::NewEnumEntryWrapper(const Key& key, + const T t) const { + return EntryType::EnumWrap(key, t, arena_); +} + +template <typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type, + int default_enum_value> +EntryType* +MapFieldLite<Key, T, key_wire_type, value_wire_type, + default_enum_value>::NewEntryWrapper(const Key& key, + const T& t) const { + return EntryType::Wrap(key, t, arena_); +} + +#undef EntryType + +// True if IsInitialized() is true for value field in all elements of t. T is +// expected to be message. It's useful to have this helper here to keep the +// protobuf compiler from ever having to emit loops in IsInitialized() methods. +// We want the C++ compiler to inline this or not as it sees fit. +template <typename Key, typename T> +bool AllAreInitialized(const Map<Key, T>& t) { + for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end(); + ++it) { + if (!it->second.IsInitialized()) return false; + } + return true; +} + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__ diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc index 98551839..61344cbb 100644 --- a/src/google/protobuf/map_field_test.cc +++ b/src/google/protobuf/map_field_test.cc @@ -35,13 +35,16 @@ #endif #include <google/protobuf/stubs/common.h> +#include <google/protobuf/arena.h> #include <google/protobuf/map.h> +#include <google/protobuf/arena_test_util.h> #include <google/protobuf/map_unittest.pb.h> #include <google/protobuf/map_test_util.h> #include <google/protobuf/unittest.pb.h> #include <google/protobuf/map_field_inl.h> #include <google/protobuf/message.h> #include <google/protobuf/repeated_field.h> +#include <google/protobuf/wire_format_lite_inl.h> #include <gtest/gtest.h> namespace google { @@ -53,6 +56,9 @@ using unittest::TestAllTypes; class MapFieldBaseStub : public MapFieldBase { public: + typedef void DestructorSkippable_; + MapFieldBaseStub() {} + explicit MapFieldBaseStub(Arena* arena) : MapFieldBase(arena) {} void SyncRepeatedFieldWithMap() const { MapFieldBase::SyncRepeatedFieldWithMap(); } @@ -63,16 +69,6 @@ class MapFieldBaseStub : public MapFieldBase { RepeatedPtrField<Message>* InternalRepeatedField() { return repeated_field_; } - // Get underlined map without synchronizing repeated field. - template <typename MapType> - const MapType& GetMap() { - return *reinterpret_cast<MapType*>(base_map_); - } - // Get underlined map without synchronizing repeated field. - template <typename MapType> - MapType* MutableMap() { - return reinterpret_cast<MapType*>(base_map_); - } bool IsMapClean() { return state_ != 0; } bool IsRepeatedClean() { return state_ != 1; } void SetMapDirty() { state_ = 0; } @@ -81,8 +77,8 @@ class MapFieldBaseStub : public MapFieldBase { class MapFieldBasePrimitiveTest : public ::testing::Test { protected: - typedef MapField<int32, int32, FieldDescriptor::TYPE_INT32, - FieldDescriptor::TYPE_INT32> MapFieldType; + typedef MapField<int32, int32, WireFormatLite::TYPE_INT32, + WireFormatLite::TYPE_INT32, false> MapFieldType; MapFieldBasePrimitiveTest() { // Get descriptors @@ -144,6 +140,38 @@ TEST_F(MapFieldBasePrimitiveTest, MutableRepeatedField) { } } +TEST_F(MapFieldBasePrimitiveTest, Arena) { + // Allocate a large initial block to avoid mallocs during hooked test. + std::vector<char> arena_block(128 * 1024); + ArenaOptions options; + options.initial_block = arena_block.data(); + options.initial_block_size = arena_block.size(); + Arena arena(options); + + { + NoHeapChecker no_heap; + + MapFieldType* map_field = + Arena::Create<MapFieldType>(&arena, &arena, default_entry_); + + // Set content in map + (*map_field->MutableMap())[100] = 101; + + // Trigger conversion to repeated field. + map_field->GetRepeatedField(); + } + + { + NoHeapChecker no_heap; + + MapFieldBaseStub* map_field = + Arena::Create<MapFieldBaseStub>(&arena, &arena); + + // Trigger conversion to repeated field. + EXPECT_TRUE(map_field->MutableRepeatedField() != NULL); + } +} + namespace { enum State { CLEAN, MAP_DIRTY, REPEATED_DIRTY }; } // anonymous namespace @@ -152,8 +180,10 @@ class MapFieldStateTest : public testing::TestWithParam<State> { public: protected: - typedef MapField<int32, int32, FieldDescriptor::TYPE_INT32, - FieldDescriptor::TYPE_INT32> MapFieldType; + typedef MapField<int32, int32, WireFormatLite::TYPE_INT32, + WireFormatLite::TYPE_INT32, false> MapFieldType; + typedef MapFieldLite<int32, int32, WireFormatLite::TYPE_INT32, + WireFormatLite::TYPE_INT32, false> MapFieldLiteType; MapFieldStateTest() : state_(GetParam()) { // Build map field const Descriptor* map_descriptor = @@ -199,9 +229,8 @@ class MapFieldStateTest MakeMapDirty(map_field); MapFieldBase* map_field_base = map_field; map_field_base->MutableRepeatedField(); - MapFieldBaseStub* stub = - reinterpret_cast<MapFieldBaseStub*>(map_field_base); - Map<int32, int32>* map = stub->MutableMap<Map<int32, int32> >(); + Map<int32, int32>* map = implicit_cast<MapFieldLiteType*>(map_field) + ->MapFieldLiteType::MutableMap(); map->clear(); Expect(map_field, REPEATED_DIRTY, 0, 1, false); @@ -213,7 +242,8 @@ class MapFieldStateTest MapFieldBaseStub* stub = reinterpret_cast<MapFieldBaseStub*>(map_field_base); - Map<int32, int32>* map = stub->MutableMap<Map<int32, int32> >(); + Map<int32, int32>* map = implicit_cast<MapFieldLiteType*>(map_field) + ->MapFieldLiteType::MutableMap(); RepeatedPtrField<Message>* repeated_field = stub->InternalRepeatedField(); switch (state) { @@ -430,40 +460,6 @@ TEST_P(MapFieldStateTest, MutableMapField) { } } -class MapFieldBaseStateStub : public MapFieldBaseStub { - public: - MapFieldBaseStateStub(Mutex* mutex, int* clean_counter, - int* completed_counter) - : mutex_(mutex), - clean_counter_(clean_counter), - completed_counter_(completed_counter) {} - ~MapFieldBaseStateStub() {} - - protected: - void SyncRepeatedFieldWithMapNoLock() const { Clean(); } - void SyncMapWithRepeatedFieldNoLock() const { Clean(); } - - private: - void Clean() const { - { - MutexLock lock(mutex_); - ++(*clean_counter_); - } - struct timespec tm; - tm.tv_sec = 0; - tm.tv_nsec = 100000000; // 100ms - nanosleep(&tm, NULL); - { - MutexLock lock(mutex_); - // No other thread should have completed while this one was initializing. - EXPECT_EQ(0, *completed_counter_); - } - } - Mutex* mutex_; - int* clean_counter_; - int* completed_counter_; -}; - } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/map_lite_test_util.cc b/src/google/protobuf/map_lite_test_util.cc new file mode 100644 index 00000000..b65b4d63 --- /dev/null +++ b/src/google/protobuf/map_lite_test_util.cc @@ -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. + +#include <google/protobuf/map_lite_test_util.h> +#include <google/protobuf/map_lite_unittest.pb.h> +#include <google/protobuf/map_test_util_impl.h> + +namespace google { +namespace protobuf { + +void MapLiteTestUtil::SetMapFields(unittest::TestMapLite* message) { + MapTestUtilImpl::SetMapFields<unittest::MapEnumLite, + unittest::MAP_ENUM_BAR_LITE, + unittest::MAP_ENUM_BAZ_LITE>(message); +} + +void MapLiteTestUtil::SetArenaMapFields(unittest::TestArenaMapLite* message) { + MapTestUtilImpl::SetArenaMapFields<unittest::MapEnumLite, + unittest::MAP_ENUM_BAR_LITE, + unittest::MAP_ENUM_BAZ_LITE>(message); +} + +void MapLiteTestUtil::SetMapFieldsInitialized(unittest::TestMapLite* message) { + MapTestUtilImpl::SetMapFieldsInitialized(message); +} + +void MapLiteTestUtil::ModifyMapFields(unittest::TestMapLite* message) { + MapTestUtilImpl::ModifyMapFields<unittest::MapEnumLite, + unittest::MAP_ENUM_FOO_LITE>(message); +} + +void MapLiteTestUtil::ExpectClear(const unittest::TestMapLite& message) { + MapTestUtilImpl::ExpectClear(message); +} + +void MapLiteTestUtil::ExpectMapFieldsSet(const unittest::TestMapLite& message) { + MapTestUtilImpl::ExpectMapFieldsSet<unittest::MapEnumLite, + unittest::MAP_ENUM_BAR_LITE, + unittest::MAP_ENUM_BAZ_LITE>(message); +} + +void MapLiteTestUtil::ExpectArenaMapFieldsSet( + const unittest::TestArenaMapLite& message) { + MapTestUtilImpl::ExpectArenaMapFieldsSet<unittest::MapEnumLite, + unittest::MAP_ENUM_BAR_LITE, + unittest::MAP_ENUM_BAZ_LITE>( + message); +} + +void MapLiteTestUtil::ExpectMapFieldsSetInitialized( + const unittest::TestMapLite& message) { + MapTestUtilImpl::ExpectMapFieldsSetInitialized<unittest::MapEnumLite, + unittest::MAP_ENUM_FOO_LITE>( + message); +} + +void MapLiteTestUtil::ExpectMapFieldsModified( + const unittest::TestMapLite& message) { + MapTestUtilImpl::ExpectMapFieldsModified<unittest::MapEnumLite, + unittest::MAP_ENUM_BAR_LITE, + unittest::MAP_ENUM_FOO_LITE>( + message); +} + +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/map_lite_test_util.h b/src/google/protobuf/map_lite_test_util.h new file mode 100644 index 00000000..77b5336f --- /dev/null +++ b/src/google/protobuf/map_lite_test_util.h @@ -0,0 +1,80 @@ +// 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_MAP_LITE_TEST_UTIL_H__ +#define GOOGLE_PROTOBUF_MAP_LITE_TEST_UTIL_H__ + +#include <google/protobuf/map_lite_unittest.pb.h> + +namespace google { +namespace protobuf { + +class MapLiteTestUtil { + public: + // Set every field in the TestMapLite message to a unique value. + static void SetMapFields(protobuf_unittest::TestMapLite* message); + + // Set every field in the TestArenaMapLite message to a unique value. + static void SetArenaMapFields(protobuf_unittest::TestArenaMapLite* message); + + // Set every field in the message to a default value. + static void SetMapFieldsInitialized(protobuf_unittest::TestMapLite* message); + + // Modify all the map fields of the messsage (which should already have been + // initialized with SetMapFields()). + static void ModifyMapFields(protobuf_unittest::TestMapLite* message); + + // Check that all fields have the values that they should have after + // SetMapFields() is called. + static void ExpectMapFieldsSet(const protobuf_unittest::TestMapLite& message); + + // Check that all fields have the values that they should have after + // SetMapFields() is called for TestArenaMapLite. + static void ExpectArenaMapFieldsSet( + const protobuf_unittest::TestArenaMapLite& message); + + // Check that all fields have the values that they should have after + // SetMapFieldsInitialized() is called. + static void ExpectMapFieldsSetInitialized( + const protobuf_unittest::TestMapLite& message); + + // Expect that the message is modified as would be expected from + // ModifyMapFields(). + static void ExpectMapFieldsModified( + const protobuf_unittest::TestMapLite& message); + + // Check that all fields are empty. + static void ExpectClear(const protobuf_unittest::TestMapLite& message); +}; + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_MAP_LITE_TEST_UTIL_H__ diff --git a/src/google/protobuf/map_lite_unittest.proto b/src/google/protobuf/map_lite_unittest.proto index cc71555d..c69e8d94 100644 --- a/src/google/protobuf/map_lite_unittest.proto +++ b/src/google/protobuf/map_lite_unittest.proto @@ -30,10 +30,104 @@ syntax = "proto2"; +option cc_enable_arenas = true; option optimize_for = LITE_RUNTIME; +import "google/protobuf/unittest_lite.proto"; + package protobuf_unittest; -message MapLite { - map<int32, int32> map_field = 1; +message TestMapLite { + map<int32 , int32 > map_int32_int32 = 1; + map<int64 , int64 > map_int64_int64 = 2; + map<uint32 , uint32 > map_uint32_uint32 = 3; + map<uint64 , uint64 > map_uint64_uint64 = 4; + map<sint32 , sint32 > map_sint32_sint32 = 5; + map<sint64 , sint64 > map_sint64_sint64 = 6; + map<fixed32 , fixed32 > map_fixed32_fixed32 = 7; + map<fixed64 , fixed64 > map_fixed64_fixed64 = 8; + map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9; + map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10; + map<int32 , float > map_int32_float = 11; + map<int32 , double > map_int32_double = 12; + map<bool , bool > map_bool_bool = 13; + map<string , string > map_string_string = 14; + map<int32 , bytes > map_int32_bytes = 15; + map<int32 , MapEnumLite> map_int32_enum = 16; + map<int32 , ForeignMessageLite> map_int32_foreign_message = 17; + map<int32, int32> teboring = 18; +} + +message TestArenaMapLite { + map<int32 , int32 > map_int32_int32 = 1; + map<int64 , int64 > map_int64_int64 = 2; + map<uint32 , uint32 > map_uint32_uint32 = 3; + map<uint64 , uint64 > map_uint64_uint64 = 4; + map<sint32 , sint32 > map_sint32_sint32 = 5; + map<sint64 , sint64 > map_sint64_sint64 = 6; + map<fixed32 , fixed32 > map_fixed32_fixed32 = 7; + map<fixed64 , fixed64 > map_fixed64_fixed64 = 8; + map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9; + map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10; + map<int32 , float > map_int32_float = 11; + map<int32 , double > map_int32_double = 12; + map<bool , bool > map_bool_bool = 13; + map<int32 , MapEnumLite> map_int32_enum = 14; + map<int32 , ForeignMessageArenaLite> map_int32_foreign_message = 15; +} + +// Test embeded message with required fields +message TestRequiredMessageMapLite { + map<int32, TestRequiredLite> map_field = 1; +} + +message TestEnumStartWithNonZeroMapLite { + map<int32, Proto2MapEnumStartWithNonZeroLite> map_field = 101; +} + +message TestEnumMapLite { + map<int32, Proto2MapEnumLite> known_map_field = 101; + map<int32, Proto2MapEnumLite> unknown_map_field = 102; +} + +message TestEnumMapPlusExtraLite { + map<int32, Proto2MapEnumPlusExtraLite> known_map_field = 101; + map<int32, Proto2MapEnumPlusExtraLite> unknown_map_field = 102; +} + +message TestMessageMapLite { + map<int32, TestAllTypesLite> map_int32_message = 1; +} + +enum Proto2MapEnumLite { + PROTO2_MAP_ENUM_FOO_LITE = 0; + PROTO2_MAP_ENUM_BAR_LITE = 1; + PROTO2_MAP_ENUM_BAZ_LITE = 2; +} + +enum Proto2MapEnumPlusExtraLite { + E_PROTO2_MAP_ENUM_FOO_LITE = 0; + E_PROTO2_MAP_ENUM_BAR_LITE = 1; + E_PROTO2_MAP_ENUM_BAZ_LITE = 2; + E_PROTO2_MAP_ENUM_EXTRA_LITE = 3; +} + +enum Proto2MapEnumStartWithNonZeroLite { + PROTO2_NON_ZERO_MAP_ENUM_FOO_LITE = 1; +} + +enum MapEnumLite { + MAP_ENUM_FOO_LITE = 0; + MAP_ENUM_BAR_LITE = 1; + MAP_ENUM_BAZ_LITE = 2; +} + +message TestRequiredLite { + required int32 a = 1; + required int32 b = 2; + required int32 c = 3; +} + +message ForeignMessageArenaLite { + optional int32 c = 1; } diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc index f9544efb..88cba1f2 100644 --- a/src/google/protobuf/map_test.cc +++ b/src/google/protobuf/map_test.cc @@ -39,7 +39,7 @@ #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/stringprintf.h> #include <google/protobuf/testing/file.h> -#include <google/protobuf/map_lite_unittest.pb.h> +#include <google/protobuf/arena_test_util.h> #include <google/protobuf/map_proto2_unittest.pb.h> #include <google/protobuf/map_unittest.pb.h> #include <google/protobuf/map_test_util.h> @@ -190,6 +190,8 @@ TEST_F(MapImplTest, MutableAt) { ExpectSingleElement(key, value2); } +#ifdef PROTOBUF_HAS_DEATH_TEST + TEST_F(MapImplTest, MutableAtNonExistDeathTest) { EXPECT_DEATH(map_.at(0), ""); } @@ -198,6 +200,8 @@ TEST_F(MapImplTest, ImmutableAtNonExistDeathTest) { EXPECT_DEATH(const_map_.at(0), ""); } +#endif // PROTOBUF_HAS_DEATH_TEST + TEST_F(MapImplTest, CountNonExist) { EXPECT_EQ(0, map_.count(0)); } @@ -544,6 +548,21 @@ TEST_F(MapImplTest, EqualRange) { EXPECT_TRUE(const_map_.end() == const_range.second); } +TEST_F(MapImplTest, ConvertToStdMap) { + map_[100] = 101; + std::map<int32, int32> std_map(map_.begin(), map_.end()); + EXPECT_EQ(1, std_map.size()); + EXPECT_EQ(101, std_map[100]); +} + +TEST_F(MapImplTest, ConvertToStdVectorOfPairs) { + map_[100] = 101; + std::vector<std::pair<int32, int32> > std_vec(map_.begin(), map_.end()); + EXPECT_EQ(1, std_vec.size()); + EXPECT_EQ(100, std_vec[0].first); + EXPECT_EQ(101, std_vec[0].second); +} + // Map Field Reflection Test ======================================== static int Func(int i, int j) { @@ -1708,6 +1727,20 @@ TEST(GeneratedMapFieldTest, MissedValueWireFormat) { EXPECT_EQ(0, message.map_int32_int32().at(1)); } +TEST(GeneratedMapFieldTest, MissedValueTextFormat) { + unittest::TestMap message; + + // No value field in text format + string text = + "map_int32_foreign_message {\n" + " key: 1234567890\n" + "}"; + + EXPECT_TRUE(google::protobuf::TextFormat::ParseFromString(text, &message)); + EXPECT_EQ(1, message.map_int32_foreign_message().size()); + EXPECT_EQ(11, message.ByteSize()); +} + TEST(GeneratedMapFieldTest, UnknownFieldWireFormat) { unittest::TestMap message; @@ -1728,16 +1761,18 @@ TEST(GeneratedMapFieldTest, CorruptedWireFormat) { EXPECT_FALSE(message.ParseFromString(data)); } -TEST(GeneratedMapFieldTest, MessageLiteMap) { - unittest::MapLite from, to; - (*from.mutable_map_field())[1] = 1; +TEST(GeneratedMapFieldTest, IsInitialized) { + unittest::TestRequiredMessageMap map_message; - string data; - from.SerializeToString(&data); - to.ParseFromString(data); + // Add an uninitialized message. + (*map_message.mutable_map_field())[0]; + EXPECT_FALSE(map_message.IsInitialized()); - EXPECT_EQ(1, to.map_field().size()); - EXPECT_EQ(1, to.map_field().at(1)); + // Initialize uninitialized message + (*map_message.mutable_map_field())[0].set_a(0); + (*map_message.mutable_map_field())[0].set_b(0); + (*map_message.mutable_map_field())[0].set_c(0); + EXPECT_TRUE(map_message.IsInitialized()); } // Generated Message Reflection Test ================================ @@ -2224,6 +2259,52 @@ TEST(TextFormatMapTest, SerializeAndParse) { } +// arena support ================================================= +TEST(ArenaTest, ParsingAndSerializingNoHeapAllocation) { + // Allocate a large initial block to avoid mallocs during hooked test. + std::vector<char> arena_block(128 * 1024); + ArenaOptions options; + options.initial_block = arena_block.data(); + options.initial_block_size = arena_block.size(); + Arena arena(options); + string data; + data.reserve(128 * 1024); + + { + NoHeapChecker no_heap; + + unittest::TestArenaMap* from = + Arena::CreateMessage<unittest::TestArenaMap>(&arena); + MapTestUtil::SetArenaMapFields(from); + from->SerializeToString(&data); + + unittest::TestArenaMap* to = + Arena::CreateMessage<unittest::TestArenaMap>(&arena); + to->ParseFromString(data); + MapTestUtil::ExpectArenaMapFieldsSet(*to); + } +} + +// Use text format parsing and serializing to test reflection api. +TEST(ArenaTest, RelfectionInTextFormat) { + Arena arena; + string data; + + TextFormat::Printer printer; + TextFormat::Parser parser; + + unittest::TestArenaMap* from = + Arena::CreateMessage<unittest::TestArenaMap>(&arena); + unittest::TestArenaMap* to = + Arena::CreateMessage<unittest::TestArenaMap>(&arena); + + MapTestUtil::SetArenaMapFields(from); + printer.PrintToString(*from, &data); + + EXPECT_TRUE(parser.ParseFromString(data, to)); + MapTestUtil::ExpectArenaMapFieldsSet(*to); +} + } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/map_test_util.cc b/src/google/protobuf/map_test_util.cc index b27c8f19..1713e373 100644 --- a/src/google/protobuf/map_test_util.cc +++ b/src/google/protobuf/map_test_util.cc @@ -29,275 +29,60 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <google/protobuf/map_test_util.h> +#include <google/protobuf/map_test_util_impl.h> #include <google/protobuf/descriptor.h> #include <google/protobuf/message.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/testing/googletest.h> -#include <gtest/gtest.h> - namespace google { namespace protobuf { void MapTestUtil::SetMapFields(unittest::TestMap* message) { - // Add first element. - (*message->mutable_map_int32_int32())[0] = 0; - (*message->mutable_map_int64_int64())[0] = 0; - (*message->mutable_map_uint32_uint32())[0] = 0; - (*message->mutable_map_uint64_uint64())[0] = 0; - (*message->mutable_map_sint32_sint32())[0] = 0; - (*message->mutable_map_sint64_sint64())[0] = 0; - (*message->mutable_map_fixed32_fixed32())[0] = 0; - (*message->mutable_map_fixed64_fixed64())[0] = 0; - (*message->mutable_map_sfixed32_sfixed32())[0] = 0; - (*message->mutable_map_sfixed64_sfixed64())[0] = 0; - (*message->mutable_map_int32_float())[0] = 0.0; - (*message->mutable_map_int32_double())[0] = 0.0; - (*message->mutable_map_bool_bool())[0] = false; - (*message->mutable_map_string_string())["0"] = "0"; - (*message->mutable_map_int32_bytes())[0] = "0"; - (*message->mutable_map_int32_enum())[0] = - unittest::MAP_ENUM_BAR; - (*message->mutable_map_int32_foreign_message())[0].set_c(0); + MapTestUtilImpl::SetMapFields<unittest::MapEnum, unittest::MAP_ENUM_BAR, + unittest::MAP_ENUM_BAZ>(message); +} - // Add second element - (*message->mutable_map_int32_int32())[1] = 1; - (*message->mutable_map_int64_int64())[1] = 1; - (*message->mutable_map_uint32_uint32())[1] = 1; - (*message->mutable_map_uint64_uint64())[1] = 1; - (*message->mutable_map_sint32_sint32())[1] = 1; - (*message->mutable_map_sint64_sint64())[1] = 1; - (*message->mutable_map_fixed32_fixed32())[1] = 1; - (*message->mutable_map_fixed64_fixed64())[1] = 1; - (*message->mutable_map_sfixed32_sfixed32())[1] = 1; - (*message->mutable_map_sfixed64_sfixed64())[1] = 1; - (*message->mutable_map_int32_float())[1] = 1.0; - (*message->mutable_map_int32_double())[1] = 1.0; - (*message->mutable_map_bool_bool())[1] = true; - (*message->mutable_map_string_string())["1"] = "1"; - (*message->mutable_map_int32_bytes())[1] = "1"; - (*message->mutable_map_int32_enum())[1] = - unittest::MAP_ENUM_BAZ; - (*message->mutable_map_int32_foreign_message())[1].set_c(1); +void MapTestUtil::SetArenaMapFields(unittest::TestArenaMap* message) { + MapTestUtilImpl::SetArenaMapFields<unittest::MapEnum, unittest::MAP_ENUM_BAR, + unittest::MAP_ENUM_BAZ>(message); } void MapTestUtil::SetMapFieldsInitialized(unittest::TestMap* message) { - // Add first element using bracket operator, which should assign default - // value automatically. - (*message->mutable_map_int32_int32())[0]; - (*message->mutable_map_int64_int64())[0]; - (*message->mutable_map_uint32_uint32())[0]; - (*message->mutable_map_uint64_uint64())[0]; - (*message->mutable_map_sint32_sint32())[0]; - (*message->mutable_map_sint64_sint64())[0]; - (*message->mutable_map_fixed32_fixed32())[0]; - (*message->mutable_map_fixed64_fixed64())[0]; - (*message->mutable_map_sfixed32_sfixed32())[0]; - (*message->mutable_map_sfixed64_sfixed64())[0]; - (*message->mutable_map_int32_float())[0]; - (*message->mutable_map_int32_double())[0]; - (*message->mutable_map_bool_bool())[0]; - (*message->mutable_map_string_string())["0"]; - (*message->mutable_map_int32_bytes())[0]; - (*message->mutable_map_int32_enum())[0]; - (*message->mutable_map_int32_foreign_message())[0]; + MapTestUtilImpl::SetMapFieldsInitialized(message); } void MapTestUtil::ModifyMapFields(unittest::TestMap* message) { - (*message->mutable_map_int32_int32())[1] = 2; - (*message->mutable_map_int64_int64())[1] = 2; - (*message->mutable_map_uint32_uint32())[1] = 2; - (*message->mutable_map_uint64_uint64())[1] = 2; - (*message->mutable_map_sint32_sint32())[1] = 2; - (*message->mutable_map_sint64_sint64())[1] = 2; - (*message->mutable_map_fixed32_fixed32())[1] = 2; - (*message->mutable_map_fixed64_fixed64())[1] = 2; - (*message->mutable_map_sfixed32_sfixed32())[1] = 2; - (*message->mutable_map_sfixed64_sfixed64())[1] = 2; - (*message->mutable_map_int32_float())[1] = 2.0; - (*message->mutable_map_int32_double())[1] = 2.0; - (*message->mutable_map_bool_bool())[1] = false; - (*message->mutable_map_string_string())["1"] = "2"; - (*message->mutable_map_int32_bytes())[1] = "2"; - (*message->mutable_map_int32_enum())[1] = - unittest::MAP_ENUM_FOO; - (*message->mutable_map_int32_foreign_message())[1].set_c(2); + MapTestUtilImpl::ModifyMapFields<unittest::MapEnum, unittest::MAP_ENUM_FOO>( + message); } void MapTestUtil::ExpectClear(const unittest::TestMap& message) { - EXPECT_EQ(0, message.map_int32_int32().size()); - EXPECT_EQ(0, message.map_int64_int64().size()); - EXPECT_EQ(0, message.map_uint32_uint32().size()); - EXPECT_EQ(0, message.map_uint64_uint64().size()); - EXPECT_EQ(0, message.map_sint32_sint32().size()); - EXPECT_EQ(0, message.map_sint64_sint64().size()); - EXPECT_EQ(0, message.map_fixed32_fixed32().size()); - EXPECT_EQ(0, message.map_fixed64_fixed64().size()); - EXPECT_EQ(0, message.map_sfixed32_sfixed32().size()); - EXPECT_EQ(0, message.map_sfixed64_sfixed64().size()); - EXPECT_EQ(0, message.map_int32_float().size()); - EXPECT_EQ(0, message.map_int32_double().size()); - EXPECT_EQ(0, message.map_bool_bool().size()); - EXPECT_EQ(0, message.map_string_string().size()); - EXPECT_EQ(0, message.map_int32_bytes().size()); - EXPECT_EQ(0, message.map_int32_enum().size()); - EXPECT_EQ(0, message.map_int32_foreign_message().size()); + MapTestUtilImpl::ExpectClear(message); } void MapTestUtil::ExpectMapFieldsSet(const unittest::TestMap& message) { - EXPECT_EQ(2, message.map_int32_int32().size()); - EXPECT_EQ(2, message.map_int64_int64().size()); - EXPECT_EQ(2, message.map_uint32_uint32().size()); - EXPECT_EQ(2, message.map_uint64_uint64().size()); - EXPECT_EQ(2, message.map_sint32_sint32().size()); - EXPECT_EQ(2, message.map_sint64_sint64().size()); - EXPECT_EQ(2, message.map_fixed32_fixed32().size()); - EXPECT_EQ(2, message.map_fixed64_fixed64().size()); - EXPECT_EQ(2, message.map_sfixed32_sfixed32().size()); - EXPECT_EQ(2, message.map_sfixed64_sfixed64().size()); - EXPECT_EQ(2, message.map_int32_float().size()); - EXPECT_EQ(2, message.map_int32_double().size()); - EXPECT_EQ(2, message.map_bool_bool().size()); - EXPECT_EQ(2, message.map_string_string().size()); - EXPECT_EQ(2, message.map_int32_bytes().size()); - EXPECT_EQ(2, message.map_int32_enum().size()); - EXPECT_EQ(2, message.map_int32_foreign_message().size()); - - EXPECT_EQ(0, message.map_int32_int32().at(0)); - EXPECT_EQ(0, message.map_int64_int64().at(0)); - EXPECT_EQ(0, message.map_uint32_uint32().at(0)); - EXPECT_EQ(0, message.map_uint64_uint64().at(0)); - EXPECT_EQ(0, message.map_sint32_sint32().at(0)); - EXPECT_EQ(0, message.map_sint64_sint64().at(0)); - EXPECT_EQ(0, message.map_fixed32_fixed32().at(0)); - EXPECT_EQ(0, message.map_fixed64_fixed64().at(0)); - EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0)); - EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0)); - EXPECT_EQ(0, message.map_int32_float().at(0)); - EXPECT_EQ(0, message.map_int32_double().at(0)); - EXPECT_EQ(false, message.map_bool_bool().at(0)); - EXPECT_EQ("0", message.map_string_string().at("0")); - EXPECT_EQ("0", message.map_int32_bytes().at(0)); - EXPECT_EQ(unittest::MAP_ENUM_BAR, message.map_int32_enum().at(0)); - EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c()); - - EXPECT_EQ(1, message.map_int32_int32().at(1)); - EXPECT_EQ(1, message.map_int64_int64().at(1)); - EXPECT_EQ(1, message.map_uint32_uint32().at(1)); - EXPECT_EQ(1, message.map_uint64_uint64().at(1)); - EXPECT_EQ(1, message.map_sint32_sint32().at(1)); - EXPECT_EQ(1, message.map_sint64_sint64().at(1)); - EXPECT_EQ(1, message.map_fixed32_fixed32().at(1)); - EXPECT_EQ(1, message.map_fixed64_fixed64().at(1)); - EXPECT_EQ(1, message.map_sfixed32_sfixed32().at(1)); - EXPECT_EQ(1, message.map_sfixed64_sfixed64().at(1)); - EXPECT_EQ(1, message.map_int32_float().at(1)); - EXPECT_EQ(1, message.map_int32_double().at(1)); - EXPECT_EQ(true, message.map_bool_bool().at(1)); - EXPECT_EQ("1", message.map_string_string().at("1")); - EXPECT_EQ("1", message.map_int32_bytes().at(1)); - EXPECT_EQ(unittest::MAP_ENUM_BAZ, message.map_int32_enum().at(1)); - EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c()); + MapTestUtilImpl::ExpectMapFieldsSet<unittest::MapEnum, unittest::MAP_ENUM_BAR, + unittest::MAP_ENUM_BAZ>(message); +} + +void MapTestUtil::ExpectArenaMapFieldsSet( + const unittest::TestArenaMap& message) { + MapTestUtilImpl::ExpectArenaMapFieldsSet< + unittest::MapEnum, unittest::MAP_ENUM_BAR, unittest::MAP_ENUM_BAZ>( + message); } void MapTestUtil::ExpectMapFieldsSetInitialized( const unittest::TestMap& message) { - EXPECT_EQ(1, message.map_int32_int32().size()); - EXPECT_EQ(1, message.map_int64_int64().size()); - EXPECT_EQ(1, message.map_uint32_uint32().size()); - EXPECT_EQ(1, message.map_uint64_uint64().size()); - EXPECT_EQ(1, message.map_sint32_sint32().size()); - EXPECT_EQ(1, message.map_sint64_sint64().size()); - EXPECT_EQ(1, message.map_fixed32_fixed32().size()); - EXPECT_EQ(1, message.map_fixed64_fixed64().size()); - EXPECT_EQ(1, message.map_sfixed32_sfixed32().size()); - EXPECT_EQ(1, message.map_sfixed64_sfixed64().size()); - EXPECT_EQ(1, message.map_int32_float().size()); - EXPECT_EQ(1, message.map_int32_double().size()); - EXPECT_EQ(1, message.map_bool_bool().size()); - EXPECT_EQ(1, message.map_string_string().size()); - EXPECT_EQ(1, message.map_int32_bytes().size()); - EXPECT_EQ(1, message.map_int32_enum().size()); - EXPECT_EQ(1, message.map_int32_foreign_message().size()); - - EXPECT_EQ(0, message.map_int32_int32().at(0)); - EXPECT_EQ(0, message.map_int64_int64().at(0)); - EXPECT_EQ(0, message.map_uint32_uint32().at(0)); - EXPECT_EQ(0, message.map_uint64_uint64().at(0)); - EXPECT_EQ(0, message.map_sint32_sint32().at(0)); - EXPECT_EQ(0, message.map_sint64_sint64().at(0)); - EXPECT_EQ(0, message.map_fixed32_fixed32().at(0)); - EXPECT_EQ(0, message.map_fixed64_fixed64().at(0)); - EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0)); - EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0)); - EXPECT_EQ(0, message.map_int32_float().at(0)); - EXPECT_EQ(0, message.map_int32_double().at(0)); - EXPECT_EQ(false, message.map_bool_bool().at(0)); - EXPECT_EQ("", message.map_string_string().at("0")); - EXPECT_EQ("", message.map_int32_bytes().at(0)); - EXPECT_EQ(unittest::MAP_ENUM_FOO, message.map_int32_enum().at(0)); - EXPECT_EQ(0, message.map_int32_foreign_message().at(0).ByteSize()); + MapTestUtilImpl::ExpectMapFieldsSetInitialized<unittest::MapEnum, + unittest::MAP_ENUM_FOO>( + message); } void MapTestUtil::ExpectMapFieldsModified( const unittest::TestMap& message) { - // ModifyMapFields only sets the second element of each field. In addition to - // verifying this, we also verify that the first element and size were *not* - // modified. - EXPECT_EQ(2, message.map_int32_int32().size()); - EXPECT_EQ(2, message.map_int64_int64().size()); - EXPECT_EQ(2, message.map_uint32_uint32().size()); - EXPECT_EQ(2, message.map_uint64_uint64().size()); - EXPECT_EQ(2, message.map_sint32_sint32().size()); - EXPECT_EQ(2, message.map_sint64_sint64().size()); - EXPECT_EQ(2, message.map_fixed32_fixed32().size()); - EXPECT_EQ(2, message.map_fixed64_fixed64().size()); - EXPECT_EQ(2, message.map_sfixed32_sfixed32().size()); - EXPECT_EQ(2, message.map_sfixed64_sfixed64().size()); - EXPECT_EQ(2, message.map_int32_float().size()); - EXPECT_EQ(2, message.map_int32_double().size()); - EXPECT_EQ(2, message.map_bool_bool().size()); - EXPECT_EQ(2, message.map_string_string().size()); - EXPECT_EQ(2, message.map_int32_bytes().size()); - EXPECT_EQ(2, message.map_int32_enum().size()); - EXPECT_EQ(2, message.map_int32_foreign_message().size()); - - EXPECT_EQ(0, message.map_int32_int32().at(0)); - EXPECT_EQ(0, message.map_int64_int64().at(0)); - EXPECT_EQ(0, message.map_uint32_uint32().at(0)); - EXPECT_EQ(0, message.map_uint64_uint64().at(0)); - EXPECT_EQ(0, message.map_sint32_sint32().at(0)); - EXPECT_EQ(0, message.map_sint64_sint64().at(0)); - EXPECT_EQ(0, message.map_fixed32_fixed32().at(0)); - EXPECT_EQ(0, message.map_fixed64_fixed64().at(0)); - EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0)); - EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0)); - EXPECT_EQ(0, message.map_int32_float().at(0)); - EXPECT_EQ(0, message.map_int32_double().at(0)); - EXPECT_EQ(false, message.map_bool_bool().at(0)); - EXPECT_EQ("0", message.map_string_string().at("0")); - EXPECT_EQ("0", message.map_int32_bytes().at(0)); - EXPECT_EQ(unittest::MAP_ENUM_BAR, message.map_int32_enum().at(0)); - EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c()); - - // Actually verify the second (modified) elements now. - EXPECT_EQ(2, message.map_int32_int32().at(1)); - EXPECT_EQ(2, message.map_int64_int64().at(1)); - EXPECT_EQ(2, message.map_uint32_uint32().at(1)); - EXPECT_EQ(2, message.map_uint64_uint64().at(1)); - EXPECT_EQ(2, message.map_sint32_sint32().at(1)); - EXPECT_EQ(2, message.map_sint64_sint64().at(1)); - EXPECT_EQ(2, message.map_fixed32_fixed32().at(1)); - EXPECT_EQ(2, message.map_fixed64_fixed64().at(1)); - EXPECT_EQ(2, message.map_sfixed32_sfixed32().at(1)); - EXPECT_EQ(2, message.map_sfixed64_sfixed64().at(1)); - EXPECT_EQ(2, message.map_int32_float().at(1)); - EXPECT_EQ(2, message.map_int32_double().at(1)); - EXPECT_EQ(false, message.map_bool_bool().at(1)); - EXPECT_EQ("2", message.map_string_string().at("1")); - EXPECT_EQ("2", message.map_int32_bytes().at(1)); - EXPECT_EQ(unittest::MAP_ENUM_FOO, message.map_int32_enum().at(1)); - EXPECT_EQ(2, message.map_int32_foreign_message().at(1).c()); + MapTestUtilImpl::ExpectMapFieldsModified< + unittest::MapEnum, unittest::MAP_ENUM_BAR, unittest::MAP_ENUM_FOO>( + message); } void MapTestUtil::ExpectMapsSize( @@ -1020,7 +805,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( *sub_message, map_int32_int32_key_); int32 val = sub_message->GetReflection()->GetInt32( *sub_message, map_int32_int32_val_); - EXPECT_EQ(map.at(key), val); + EXPECT_EQ(map[key], val); } } { @@ -1034,7 +819,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( *sub_message, map_int64_int64_key_); int64 val = sub_message->GetReflection()->GetInt64( *sub_message, map_int64_int64_val_); - EXPECT_EQ(map.at(key), val); + EXPECT_EQ(map[key], val); } } { @@ -1048,7 +833,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( *sub_message, map_uint32_uint32_key_); uint32 val = sub_message->GetReflection()->GetUInt32( *sub_message, map_uint32_uint32_val_); - EXPECT_EQ(map.at(key), val); + EXPECT_EQ(map[key], val); } } { @@ -1062,7 +847,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( *sub_message, map_uint64_uint64_key_); uint64 val = sub_message->GetReflection()->GetUInt64( *sub_message, map_uint64_uint64_val_); - EXPECT_EQ(map.at(key), val); + EXPECT_EQ(map[key], val); } } { @@ -1076,7 +861,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( *sub_message, map_sint32_sint32_key_); int32 val = sub_message->GetReflection()->GetInt32( *sub_message, map_sint32_sint32_val_); - EXPECT_EQ(map.at(key), val); + EXPECT_EQ(map[key], val); } } { @@ -1090,7 +875,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( *sub_message, map_sint64_sint64_key_); int64 val = sub_message->GetReflection()->GetInt64( *sub_message, map_sint64_sint64_val_); - EXPECT_EQ(map.at(key), val); + EXPECT_EQ(map[key], val); } } { @@ -1104,7 +889,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( *sub_message, map_fixed32_fixed32_key_); uint32 val = sub_message->GetReflection()->GetUInt32( *sub_message, map_fixed32_fixed32_val_); - EXPECT_EQ(map.at(key), val); + EXPECT_EQ(map[key], val); } } { @@ -1118,7 +903,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( *sub_message, map_fixed64_fixed64_key_); uint64 val = sub_message->GetReflection()->GetUInt64( *sub_message, map_fixed64_fixed64_val_); - EXPECT_EQ(map.at(key), val); + EXPECT_EQ(map[key], val); } } { @@ -1132,7 +917,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( *sub_message, map_sfixed32_sfixed32_key_); int32 val = sub_message->GetReflection()->GetInt32( *sub_message, map_sfixed32_sfixed32_val_); - EXPECT_EQ(map.at(key), val); + EXPECT_EQ(map[key], val); } } { @@ -1146,7 +931,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( *sub_message, map_sfixed64_sfixed64_key_); int64 val = sub_message->GetReflection()->GetInt64( *sub_message, map_sfixed64_sfixed64_val_); - EXPECT_EQ(map.at(key), val); + EXPECT_EQ(map[key], val); } } { @@ -1160,7 +945,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( *sub_message, map_int32_float_key_); float val = sub_message->GetReflection()->GetFloat( *sub_message, map_int32_float_val_); - EXPECT_EQ(map.at(key), val); + EXPECT_EQ(map[key], val); } } { @@ -1174,7 +959,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( *sub_message, map_int32_double_key_); double val = sub_message->GetReflection()->GetDouble( *sub_message, map_int32_double_val_); - EXPECT_EQ(map.at(key), val); + EXPECT_EQ(map[key], val); } } { @@ -1188,7 +973,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( *sub_message, map_bool_bool_key_); bool val = sub_message->GetReflection()->GetBool( *sub_message, map_bool_bool_val_); - EXPECT_EQ(map.at(key), val); + EXPECT_EQ(map[key], val); } } { @@ -1202,7 +987,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( *sub_message, map_string_string_key_); string val = sub_message->GetReflection()->GetString( *sub_message, map_string_string_val_); - EXPECT_EQ(map.at(key), val); + EXPECT_EQ(map[key], val); } } { @@ -1216,7 +1001,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( *sub_message, map_int32_bytes_key_); string val = sub_message->GetReflection()->GetString( *sub_message, map_int32_bytes_val_); - EXPECT_EQ(map.at(key), val); + EXPECT_EQ(map[key], val); } } { @@ -1230,7 +1015,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( *sub_message, map_int32_enum_key_); const EnumValueDescriptor* val = sub_message->GetReflection()->GetEnum( *sub_message, map_int32_enum_val_); - EXPECT_EQ(map.at(key), val); + EXPECT_EQ(map[key], val); } } { @@ -1246,7 +1031,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection( *sub_message, map_int32_foreign_message_val_); int32 val = foreign_message.GetReflection()->GetInt32( foreign_message, foreign_c_); - EXPECT_EQ(map.at(key), val); + EXPECT_EQ(map[key], val); } } } @@ -1468,8 +1253,9 @@ void MapTestUtil::MapReflectionTester::ExpectMapEntryClearViaReflection( sub_message = reflection->AddMessage(message, F("map_int32_enum")); EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, key_descriptor)); - EXPECT_EQ(0, sub_message->GetReflection()->GetEnum(*sub_message, - value_descriptor)); + EXPECT_EQ(0, sub_message->GetReflection() + ->GetEnum(*sub_message, value_descriptor) + ->number()); } // Map using message as value has been tested in other place. Thus, we don't // test it here. diff --git a/src/google/protobuf/map_test_util.h b/src/google/protobuf/map_test_util.h index 653cf107..f437e33e 100644 --- a/src/google/protobuf/map_test_util.h +++ b/src/google/protobuf/map_test_util.h @@ -40,9 +40,12 @@ namespace unittest = ::protobuf_unittest; class MapTestUtil { public: - // Set every field in the message to a unique value. + // Set every field in the TestMap message to a unique value. static void SetMapFields(unittest::TestMap* message); + // Set every field in the TestArenaMap message to a unique value. + static void SetArenaMapFields(unittest::TestArenaMap* message); + // Set every field in the message to a default value. static void SetMapFieldsInitialized(unittest::TestMap* message); @@ -55,6 +58,10 @@ class MapTestUtil { static void ExpectMapFieldsSet(const unittest::TestMap& message); // Check that all fields have the values that they should have after + // SetMapFields() is called for TestArenaMap. + static void ExpectArenaMapFieldsSet(const unittest::TestArenaMap& message); + + // Check that all fields have the values that they should have after // SetMapFieldsInitialized() is called. static void ExpectMapFieldsSetInitialized( const unittest::TestMap& message); diff --git a/src/google/protobuf/map_test_util_impl.h b/src/google/protobuf/map_test_util_impl.h new file mode 100644 index 00000000..5e7882a1 --- /dev/null +++ b/src/google/protobuf/map_test_util_impl.h @@ -0,0 +1,474 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__ +#define GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__ + +#include <google/protobuf/stubs/common.h> + + +#define EXPECT_TRUE GOOGLE_CHECK +#define ASSERT_TRUE GOOGLE_CHECK +#define EXPECT_FALSE(COND) GOOGLE_CHECK(!(COND)) +#define EXPECT_EQ GOOGLE_CHECK_EQ +#define ASSERT_EQ GOOGLE_CHECK_EQ + +namespace google { +namespace protobuf_unittest {} // forward declaration + +namespace protobuf { + +namespace unittest = ::protobuf_unittest; + +class MapTestUtilImpl { + public: + // Set every field in the TestMap message to a unique value. + template <typename EnumType, EnumType enum_value0, + EnumType enum_value1, typename MapMessage> + static void SetMapFields(MapMessage* message); + + // Set every field in the TestArenaMap message to a unique value. + template <typename EnumType, EnumType enum_value0, + EnumType enum_value1, typename MapMessage> + static void SetArenaMapFields(MapMessage* message); + + // Set every field in the message to a default value. + template <typename MapMessage> + static void SetMapFieldsInitialized(MapMessage* message); + + // Modify all the map fields of the messsage (which should already have been + // initialized with SetMapFields()). + template <typename EnumType, EnumType enum_value, typename MapMessage> + static void ModifyMapFields(MapMessage* message); + + // Check that all fields have the values that they should have after + // SetMapFields() is called. + template <typename EnumType, EnumType enum_value0, + EnumType enum_value1, typename MapMessage> + static void ExpectMapFieldsSet(const MapMessage& message); + + // Check that all fields have the values that they should have after + // SetMapFields() is called for TestArenaMap. + template <typename EnumType, EnumType enum_value0, + EnumType enum_value1, typename MapMessage> + static void ExpectArenaMapFieldsSet(const MapMessage& message); + + // Check that all fields have the values that they should have after + // SetMapFieldsInitialized() is called. + template <typename EnumType, EnumType enum_value, typename MapMessage> + static void ExpectMapFieldsSetInitialized(const MapMessage& message); + + // Expect that the message is modified as would be expected from + // ModifyMapFields(). + template <typename EnumType, EnumType enum_value0, + EnumType enum_value1, typename MapMessage> + static void ExpectMapFieldsModified(const MapMessage& message); + + // Check that all fields are empty. + template <typename MapMessage> + static void ExpectClear(const MapMessage& message); + + // // Check that all map fields have the given size. + // template <typename MapMessage> + // static void ExpectMapsSize(const MapMessage& message, int size); + + // // Get pointers of map entries at given index. + // static std::vector<const Message*> GetMapEntries( + // const MapMessage& message, int index); + + // // Get pointers of map entries from release. + // static std::vector<const Message*> GetMapEntriesFromRelease( + // MapMessage* message); +}; + +template <typename EnumType, EnumType enum_value0, + EnumType enum_value1, typename MapMessage> +void MapTestUtilImpl::SetMapFields(MapMessage* message) { + // Add first element. + (*message->mutable_map_int32_int32())[0] = 0; + (*message->mutable_map_int64_int64())[0] = 0; + (*message->mutable_map_uint32_uint32())[0] = 0; + (*message->mutable_map_uint64_uint64())[0] = 0; + (*message->mutable_map_sint32_sint32())[0] = 0; + (*message->mutable_map_sint64_sint64())[0] = 0; + (*message->mutable_map_fixed32_fixed32())[0] = 0; + (*message->mutable_map_fixed64_fixed64())[0] = 0; + (*message->mutable_map_sfixed32_sfixed32())[0] = 0; + (*message->mutable_map_sfixed64_sfixed64())[0] = 0; + (*message->mutable_map_int32_float())[0] = 0.0; + (*message->mutable_map_int32_double())[0] = 0.0; + (*message->mutable_map_bool_bool())[0] = false; + (*message->mutable_map_string_string())["0"] = "0"; + (*message->mutable_map_int32_bytes())[0] = "0"; + (*message->mutable_map_int32_enum())[0] = enum_value0; + (*message->mutable_map_int32_foreign_message())[0].set_c(0); + + // Add second element + (*message->mutable_map_int32_int32())[1] = 1; + (*message->mutable_map_int64_int64())[1] = 1; + (*message->mutable_map_uint32_uint32())[1] = 1; + (*message->mutable_map_uint64_uint64())[1] = 1; + (*message->mutable_map_sint32_sint32())[1] = 1; + (*message->mutable_map_sint64_sint64())[1] = 1; + (*message->mutable_map_fixed32_fixed32())[1] = 1; + (*message->mutable_map_fixed64_fixed64())[1] = 1; + (*message->mutable_map_sfixed32_sfixed32())[1] = 1; + (*message->mutable_map_sfixed64_sfixed64())[1] = 1; + (*message->mutable_map_int32_float())[1] = 1.0; + (*message->mutable_map_int32_double())[1] = 1.0; + (*message->mutable_map_bool_bool())[1] = true; + (*message->mutable_map_string_string())["1"] = "1"; + (*message->mutable_map_int32_bytes())[1] = "1"; + (*message->mutable_map_int32_enum())[1] = enum_value1; + (*message->mutable_map_int32_foreign_message())[1].set_c(1); +} + +template <typename EnumType, EnumType enum_value0, + EnumType enum_value1, typename MapMessage> +void MapTestUtilImpl::SetArenaMapFields(MapMessage* message) { + // Add first element. + (*message->mutable_map_int32_int32())[0] = 0; + (*message->mutable_map_int64_int64())[0] = 0; + (*message->mutable_map_uint32_uint32())[0] = 0; + (*message->mutable_map_uint64_uint64())[0] = 0; + (*message->mutable_map_sint32_sint32())[0] = 0; + (*message->mutable_map_sint64_sint64())[0] = 0; + (*message->mutable_map_fixed32_fixed32())[0] = 0; + (*message->mutable_map_fixed64_fixed64())[0] = 0; + (*message->mutable_map_sfixed32_sfixed32())[0] = 0; + (*message->mutable_map_sfixed64_sfixed64())[0] = 0; + (*message->mutable_map_int32_float())[0] = 0.0; + (*message->mutable_map_int32_double())[0] = 0.0; + (*message->mutable_map_bool_bool())[0] = false; + (*message->mutable_map_int32_enum())[0] = enum_value0; + (*message->mutable_map_int32_foreign_message())[0].set_c(0); + + // Add second element + (*message->mutable_map_int32_int32())[1] = 1; + (*message->mutable_map_int64_int64())[1] = 1; + (*message->mutable_map_uint32_uint32())[1] = 1; + (*message->mutable_map_uint64_uint64())[1] = 1; + (*message->mutable_map_sint32_sint32())[1] = 1; + (*message->mutable_map_sint64_sint64())[1] = 1; + (*message->mutable_map_fixed32_fixed32())[1] = 1; + (*message->mutable_map_fixed64_fixed64())[1] = 1; + (*message->mutable_map_sfixed32_sfixed32())[1] = 1; + (*message->mutable_map_sfixed64_sfixed64())[1] = 1; + (*message->mutable_map_int32_float())[1] = 1.0; + (*message->mutable_map_int32_double())[1] = 1.0; + (*message->mutable_map_bool_bool())[1] = true; + (*message->mutable_map_int32_enum())[1] = enum_value1; + (*message->mutable_map_int32_foreign_message())[1].set_c(1); +} + +template <typename MapMessage> +void MapTestUtilImpl::SetMapFieldsInitialized(MapMessage* message) { + // Add first element using bracket operator, which should assign default + // value automatically. + (*message->mutable_map_int32_int32())[0]; + (*message->mutable_map_int64_int64())[0]; + (*message->mutable_map_uint32_uint32())[0]; + (*message->mutable_map_uint64_uint64())[0]; + (*message->mutable_map_sint32_sint32())[0]; + (*message->mutable_map_sint64_sint64())[0]; + (*message->mutable_map_fixed32_fixed32())[0]; + (*message->mutable_map_fixed64_fixed64())[0]; + (*message->mutable_map_sfixed32_sfixed32())[0]; + (*message->mutable_map_sfixed64_sfixed64())[0]; + (*message->mutable_map_int32_float())[0]; + (*message->mutable_map_int32_double())[0]; + (*message->mutable_map_bool_bool())[0]; + (*message->mutable_map_string_string())["0"]; + (*message->mutable_map_int32_bytes())[0]; + (*message->mutable_map_int32_enum())[0]; + (*message->mutable_map_int32_foreign_message())[0]; +} + +template <typename EnumType, EnumType enum_value, typename MapMessage> +void MapTestUtilImpl::ModifyMapFields(MapMessage* message) { + (*message->mutable_map_int32_int32())[1] = 2; + (*message->mutable_map_int64_int64())[1] = 2; + (*message->mutable_map_uint32_uint32())[1] = 2; + (*message->mutable_map_uint64_uint64())[1] = 2; + (*message->mutable_map_sint32_sint32())[1] = 2; + (*message->mutable_map_sint64_sint64())[1] = 2; + (*message->mutable_map_fixed32_fixed32())[1] = 2; + (*message->mutable_map_fixed64_fixed64())[1] = 2; + (*message->mutable_map_sfixed32_sfixed32())[1] = 2; + (*message->mutable_map_sfixed64_sfixed64())[1] = 2; + (*message->mutable_map_int32_float())[1] = 2.0; + (*message->mutable_map_int32_double())[1] = 2.0; + (*message->mutable_map_bool_bool())[1] = false; + (*message->mutable_map_string_string())["1"] = "2"; + (*message->mutable_map_int32_bytes())[1] = "2"; + (*message->mutable_map_int32_enum())[1] = enum_value; + (*message->mutable_map_int32_foreign_message())[1].set_c(2); +} + +template <typename MapMessage> +void MapTestUtilImpl::ExpectClear(const MapMessage& message) { + EXPECT_EQ(0, message.map_int32_int32().size()); + EXPECT_EQ(0, message.map_int64_int64().size()); + EXPECT_EQ(0, message.map_uint32_uint32().size()); + EXPECT_EQ(0, message.map_uint64_uint64().size()); + EXPECT_EQ(0, message.map_sint32_sint32().size()); + EXPECT_EQ(0, message.map_sint64_sint64().size()); + EXPECT_EQ(0, message.map_fixed32_fixed32().size()); + EXPECT_EQ(0, message.map_fixed64_fixed64().size()); + EXPECT_EQ(0, message.map_sfixed32_sfixed32().size()); + EXPECT_EQ(0, message.map_sfixed64_sfixed64().size()); + EXPECT_EQ(0, message.map_int32_float().size()); + EXPECT_EQ(0, message.map_int32_double().size()); + EXPECT_EQ(0, message.map_bool_bool().size()); + EXPECT_EQ(0, message.map_string_string().size()); + EXPECT_EQ(0, message.map_int32_bytes().size()); + EXPECT_EQ(0, message.map_int32_enum().size()); + EXPECT_EQ(0, message.map_int32_foreign_message().size()); +} + + + +template <typename EnumType, EnumType enum_value0, + EnumType enum_value1, typename MapMessage> +void MapTestUtilImpl::ExpectMapFieldsSet(const MapMessage& message) { + EXPECT_EQ(2, message.map_int32_int32().size()); + EXPECT_EQ(2, message.map_int64_int64().size()); + EXPECT_EQ(2, message.map_uint32_uint32().size()); + EXPECT_EQ(2, message.map_uint64_uint64().size()); + EXPECT_EQ(2, message.map_sint32_sint32().size()); + EXPECT_EQ(2, message.map_sint64_sint64().size()); + EXPECT_EQ(2, message.map_fixed32_fixed32().size()); + EXPECT_EQ(2, message.map_fixed64_fixed64().size()); + EXPECT_EQ(2, message.map_sfixed32_sfixed32().size()); + EXPECT_EQ(2, message.map_sfixed64_sfixed64().size()); + EXPECT_EQ(2, message.map_int32_float().size()); + EXPECT_EQ(2, message.map_int32_double().size()); + EXPECT_EQ(2, message.map_bool_bool().size()); + EXPECT_EQ(2, message.map_string_string().size()); + EXPECT_EQ(2, message.map_int32_bytes().size()); + EXPECT_EQ(2, message.map_int32_enum().size()); + EXPECT_EQ(2, message.map_int32_foreign_message().size()); + + EXPECT_EQ(0, message.map_int32_int32().at(0)); + EXPECT_EQ(0, message.map_int64_int64().at(0)); + EXPECT_EQ(0, message.map_uint32_uint32().at(0)); + EXPECT_EQ(0, message.map_uint64_uint64().at(0)); + EXPECT_EQ(0, message.map_sint32_sint32().at(0)); + EXPECT_EQ(0, message.map_sint64_sint64().at(0)); + EXPECT_EQ(0, message.map_fixed32_fixed32().at(0)); + EXPECT_EQ(0, message.map_fixed64_fixed64().at(0)); + EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0)); + EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0)); + EXPECT_EQ(0, message.map_int32_float().at(0)); + EXPECT_EQ(0, message.map_int32_double().at(0)); + EXPECT_EQ(false, message.map_bool_bool().at(0)); + EXPECT_EQ("0", message.map_string_string().at("0")); + EXPECT_EQ("0", message.map_int32_bytes().at(0)); + EXPECT_EQ(enum_value0, message.map_int32_enum().at(0)); + EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c()); + + EXPECT_EQ(1, message.map_int32_int32().at(1)); + EXPECT_EQ(1, message.map_int64_int64().at(1)); + EXPECT_EQ(1, message.map_uint32_uint32().at(1)); + EXPECT_EQ(1, message.map_uint64_uint64().at(1)); + EXPECT_EQ(1, message.map_sint32_sint32().at(1)); + EXPECT_EQ(1, message.map_sint64_sint64().at(1)); + EXPECT_EQ(1, message.map_fixed32_fixed32().at(1)); + EXPECT_EQ(1, message.map_fixed64_fixed64().at(1)); + EXPECT_EQ(1, message.map_sfixed32_sfixed32().at(1)); + EXPECT_EQ(1, message.map_sfixed64_sfixed64().at(1)); + EXPECT_EQ(1, message.map_int32_float().at(1)); + EXPECT_EQ(1, message.map_int32_double().at(1)); + EXPECT_EQ(true, message.map_bool_bool().at(1)); + EXPECT_EQ("1", message.map_string_string().at("1")); + EXPECT_EQ("1", message.map_int32_bytes().at(1)); + EXPECT_EQ(enum_value1, message.map_int32_enum().at(1)); + EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c()); +} + +template <typename EnumType, EnumType enum_value0, + EnumType enum_value1, typename MapMessage> +void MapTestUtilImpl::ExpectArenaMapFieldsSet(const MapMessage& message) { + EXPECT_EQ(2, message.map_int32_int32().size()); + EXPECT_EQ(2, message.map_int64_int64().size()); + EXPECT_EQ(2, message.map_uint32_uint32().size()); + EXPECT_EQ(2, message.map_uint64_uint64().size()); + EXPECT_EQ(2, message.map_sint32_sint32().size()); + EXPECT_EQ(2, message.map_sint64_sint64().size()); + EXPECT_EQ(2, message.map_fixed32_fixed32().size()); + EXPECT_EQ(2, message.map_fixed64_fixed64().size()); + EXPECT_EQ(2, message.map_sfixed32_sfixed32().size()); + EXPECT_EQ(2, message.map_sfixed64_sfixed64().size()); + EXPECT_EQ(2, message.map_int32_float().size()); + EXPECT_EQ(2, message.map_int32_double().size()); + EXPECT_EQ(2, message.map_bool_bool().size()); + EXPECT_EQ(2, message.map_int32_enum().size()); + EXPECT_EQ(2, message.map_int32_foreign_message().size()); + + EXPECT_EQ(0, message.map_int32_int32().at(0)); + EXPECT_EQ(0, message.map_int64_int64().at(0)); + EXPECT_EQ(0, message.map_uint32_uint32().at(0)); + EXPECT_EQ(0, message.map_uint64_uint64().at(0)); + EXPECT_EQ(0, message.map_sint32_sint32().at(0)); + EXPECT_EQ(0, message.map_sint64_sint64().at(0)); + EXPECT_EQ(0, message.map_fixed32_fixed32().at(0)); + EXPECT_EQ(0, message.map_fixed64_fixed64().at(0)); + EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0)); + EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0)); + EXPECT_EQ(0, message.map_int32_float().at(0)); + EXPECT_EQ(0, message.map_int32_double().at(0)); + EXPECT_EQ(false, message.map_bool_bool().at(0)); + EXPECT_EQ(enum_value0, message.map_int32_enum().at(0)); + EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c()); + + EXPECT_EQ(1, message.map_int32_int32().at(1)); + EXPECT_EQ(1, message.map_int64_int64().at(1)); + EXPECT_EQ(1, message.map_uint32_uint32().at(1)); + EXPECT_EQ(1, message.map_uint64_uint64().at(1)); + EXPECT_EQ(1, message.map_sint32_sint32().at(1)); + EXPECT_EQ(1, message.map_sint64_sint64().at(1)); + EXPECT_EQ(1, message.map_fixed32_fixed32().at(1)); + EXPECT_EQ(1, message.map_fixed64_fixed64().at(1)); + EXPECT_EQ(1, message.map_sfixed32_sfixed32().at(1)); + EXPECT_EQ(1, message.map_sfixed64_sfixed64().at(1)); + EXPECT_EQ(1, message.map_int32_float().at(1)); + EXPECT_EQ(1, message.map_int32_double().at(1)); + EXPECT_EQ(true, message.map_bool_bool().at(1)); + EXPECT_EQ(enum_value1, message.map_int32_enum().at(1)); + EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c()); +} + +template <typename EnumType, EnumType enum_value, typename MapMessage> +void MapTestUtilImpl::ExpectMapFieldsSetInitialized( + const MapMessage& message) { + EXPECT_EQ(1, message.map_int32_int32().size()); + EXPECT_EQ(1, message.map_int64_int64().size()); + EXPECT_EQ(1, message.map_uint32_uint32().size()); + EXPECT_EQ(1, message.map_uint64_uint64().size()); + EXPECT_EQ(1, message.map_sint32_sint32().size()); + EXPECT_EQ(1, message.map_sint64_sint64().size()); + EXPECT_EQ(1, message.map_fixed32_fixed32().size()); + EXPECT_EQ(1, message.map_fixed64_fixed64().size()); + EXPECT_EQ(1, message.map_sfixed32_sfixed32().size()); + EXPECT_EQ(1, message.map_sfixed64_sfixed64().size()); + EXPECT_EQ(1, message.map_int32_float().size()); + EXPECT_EQ(1, message.map_int32_double().size()); + EXPECT_EQ(1, message.map_bool_bool().size()); + EXPECT_EQ(1, message.map_string_string().size()); + EXPECT_EQ(1, message.map_int32_bytes().size()); + EXPECT_EQ(1, message.map_int32_enum().size()); + EXPECT_EQ(1, message.map_int32_foreign_message().size()); + + EXPECT_EQ(0, message.map_int32_int32().at(0)); + EXPECT_EQ(0, message.map_int64_int64().at(0)); + EXPECT_EQ(0, message.map_uint32_uint32().at(0)); + EXPECT_EQ(0, message.map_uint64_uint64().at(0)); + EXPECT_EQ(0, message.map_sint32_sint32().at(0)); + EXPECT_EQ(0, message.map_sint64_sint64().at(0)); + EXPECT_EQ(0, message.map_fixed32_fixed32().at(0)); + EXPECT_EQ(0, message.map_fixed64_fixed64().at(0)); + EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0)); + EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0)); + EXPECT_EQ(0, message.map_int32_float().at(0)); + EXPECT_EQ(0, message.map_int32_double().at(0)); + EXPECT_EQ(false, message.map_bool_bool().at(0)); + EXPECT_EQ("", message.map_string_string().at("0")); + EXPECT_EQ("", message.map_int32_bytes().at(0)); + EXPECT_EQ(enum_value, message.map_int32_enum().at(0)); + EXPECT_EQ(0, message.map_int32_foreign_message().at(0).ByteSize()); +} + +template <typename EnumType, EnumType enum_value0, + EnumType enum_value1, typename MapMessage> +void MapTestUtilImpl::ExpectMapFieldsModified( + const MapMessage& message) { + // ModifyMapFields only sets the second element of each field. In addition to + // verifying this, we also verify that the first element and size were *not* + // modified. + EXPECT_EQ(2, message.map_int32_int32().size()); + EXPECT_EQ(2, message.map_int64_int64().size()); + EXPECT_EQ(2, message.map_uint32_uint32().size()); + EXPECT_EQ(2, message.map_uint64_uint64().size()); + EXPECT_EQ(2, message.map_sint32_sint32().size()); + EXPECT_EQ(2, message.map_sint64_sint64().size()); + EXPECT_EQ(2, message.map_fixed32_fixed32().size()); + EXPECT_EQ(2, message.map_fixed64_fixed64().size()); + EXPECT_EQ(2, message.map_sfixed32_sfixed32().size()); + EXPECT_EQ(2, message.map_sfixed64_sfixed64().size()); + EXPECT_EQ(2, message.map_int32_float().size()); + EXPECT_EQ(2, message.map_int32_double().size()); + EXPECT_EQ(2, message.map_bool_bool().size()); + EXPECT_EQ(2, message.map_string_string().size()); + EXPECT_EQ(2, message.map_int32_bytes().size()); + EXPECT_EQ(2, message.map_int32_enum().size()); + EXPECT_EQ(2, message.map_int32_foreign_message().size()); + + EXPECT_EQ(0, message.map_int32_int32().at(0)); + EXPECT_EQ(0, message.map_int64_int64().at(0)); + EXPECT_EQ(0, message.map_uint32_uint32().at(0)); + EXPECT_EQ(0, message.map_uint64_uint64().at(0)); + EXPECT_EQ(0, message.map_sint32_sint32().at(0)); + EXPECT_EQ(0, message.map_sint64_sint64().at(0)); + EXPECT_EQ(0, message.map_fixed32_fixed32().at(0)); + EXPECT_EQ(0, message.map_fixed64_fixed64().at(0)); + EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0)); + EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0)); + EXPECT_EQ(0, message.map_int32_float().at(0)); + EXPECT_EQ(0, message.map_int32_double().at(0)); + EXPECT_EQ(false, message.map_bool_bool().at(0)); + EXPECT_EQ("0", message.map_string_string().at("0")); + EXPECT_EQ("0", message.map_int32_bytes().at(0)); + EXPECT_EQ(enum_value0, message.map_int32_enum().at(0)); + EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c()); + + // Actually verify the second (modified) elements now. + EXPECT_EQ(2, message.map_int32_int32().at(1)); + EXPECT_EQ(2, message.map_int64_int64().at(1)); + EXPECT_EQ(2, message.map_uint32_uint32().at(1)); + EXPECT_EQ(2, message.map_uint64_uint64().at(1)); + EXPECT_EQ(2, message.map_sint32_sint32().at(1)); + EXPECT_EQ(2, message.map_sint64_sint64().at(1)); + EXPECT_EQ(2, message.map_fixed32_fixed32().at(1)); + EXPECT_EQ(2, message.map_fixed64_fixed64().at(1)); + EXPECT_EQ(2, message.map_sfixed32_sfixed32().at(1)); + EXPECT_EQ(2, message.map_sfixed64_sfixed64().at(1)); + EXPECT_EQ(2, message.map_int32_float().at(1)); + EXPECT_EQ(2, message.map_int32_double().at(1)); + EXPECT_EQ(false, message.map_bool_bool().at(1)); + EXPECT_EQ("2", message.map_string_string().at("1")); + EXPECT_EQ("2", message.map_int32_bytes().at(1)); + EXPECT_EQ(enum_value1, message.map_int32_enum().at(1)); + EXPECT_EQ(2, message.map_int32_foreign_message().at(1).c()); +} + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__ diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h index 88a6d7b8..278b78ae 100644 --- a/src/google/protobuf/map_type_handler.h +++ b/src/google/protobuf/map_type_handler.h @@ -31,8 +31,8 @@ #ifndef GOOGLE_PROTOBUF_TYPE_HANDLER_H__ #define GOOGLE_PROTOBUF_TYPE_HANDLER_H__ +#include <google/protobuf/arena.h> #include <google/protobuf/generated_message_util.h> -#include <google/protobuf/message.h> #include <google/protobuf/wire_format_lite_inl.h> namespace google { @@ -92,6 +92,28 @@ class MapValueInitializer<false, Type> { static inline void Initialize(Type& value, int default_enum_value) {} }; +template <typename Type, bool is_arena_constructable> +class MapArenaMessageCreator { + public: + // Use arena to create message if Type is arena constructable. Otherwise, + // create the message on heap. + static inline Type* CreateMessage(Arena* arena); +}; +template <typename Type> +class MapArenaMessageCreator<Type, true> { + public: + static inline Type* CreateMessage(Arena* arena) { + return Arena::CreateMessage<Type>(arena); + } +}; +template <typename Type> +class MapArenaMessageCreator<Type, false> { + public: + static inline Type* CreateMessage(Arena* arena) { + return new Type; + } +}; + // Handlers for key/value stored type in MapField. ================== // Handler for message @@ -124,20 +146,24 @@ class MapCppTypeHandler : public MapCommonTypeHandler<Type> { *value = const_cast<Type*>(&Type::default_instance()); } // Initialize value when constructing MapEntry - static inline void Initialize(Type** x) { *x = NULL; } + static inline void Initialize(Type** x, Arena* arena) { *x = NULL; } // Same as above, but use default_enum_value to initialize enum type value. static inline void InitializeMaybeByDefaultEnum( - Type** x, int default_enum_value) { + Type** x, int default_enum_value, Arena* arena) { *x = NULL; } // Initialize value for the first time mutable accessor is called. - static inline void EnsureMutable(Type** value) { - if (*value == NULL) *value = new Type; + static inline void EnsureMutable(Type** value, Arena* arena) { + if (*value == NULL) { + *value = + MapArenaMessageCreator<Type, Arena::is_arena_constructable<Type>:: + type::value>::CreateMessage(arena); + } } // Return default instance if value is not initialized when calling const // reference accessor. - static inline const Type& DefaultIfNotInitialized(Type* value, - Type* default_value) { + static inline const Type& DefaultIfNotInitialized(const Type* value, + const Type* default_value) { return value != NULL ? *value : *default_value; } // Check if all required fields have values set. @@ -166,18 +192,23 @@ class MapCppTypeHandler<string> : public MapCommonTypeHandler<string> { if (ptr != &::google::protobuf::internal::GetEmptyString()) delete ptr; } static inline void AssignDefaultValue(string** value) {} - static inline void Initialize(string** value) { + static inline void Initialize(string** value, Arena* arena) { *value = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + if (arena != NULL) arena->Own(*value); } static inline void InitializeMaybeByDefaultEnum( - string** value, int default_enum_value) { + string** value, int default_enum_value, Arena* arena) { *value = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + if (arena != NULL) arena->Own(*value); } - static inline void EnsureMutable(string** value) { - if (*value == &::google::protobuf::internal::GetEmptyString()) *value = new string; + static inline void EnsureMutable(string** value, Arena* arena) { + if (*value == &::google::protobuf::internal::GetEmptyString()) { + *value = Arena::Create<string>(arena); + } } - static inline const string& DefaultIfNotInitialized(string* value, - string* default_value) { + static inline const string& DefaultIfNotInitialized( + const string* value, + const string* default_value) { return value != default_value ? *value : *default_value; } static inline bool IsInitialized(string* value) { return true; } @@ -210,12 +241,13 @@ class MapPrimitiveTypeHandler : public MapCommonTypeHandler<Type> { int default_enum_value) { \ *value = static_cast<CType>(default_enum_value); \ } \ - static inline void Initialize(CType* value) { *value = 0; } \ + static inline void Initialize(CType* value, Arena* arena) { *value = 0; } \ static inline void InitializeMaybeByDefaultEnum(CType* value, \ - int default_enum_value) { \ + int default_enum_value, \ + Arena* arena) { \ *value = static_cast<CType>(default_enum_value); \ } \ - static inline void EnsureMutable(CType* value) {} \ + static inline void EnsureMutable(CType* value, Arena* arena) {} \ }; PRIMITIVE_HANDLER(int32 ) @@ -228,13 +260,13 @@ PRIMITIVE_HANDLER(bool ) #undef PRIMITIVE_HANDLER -// Define constants for given proto field type -template <FieldDescriptor::Type Type> -class MapFieldTypeTraits {}; +// Define constants for given wire field type +template <WireFormatLite::FieldType field_type> +class MapWireFieldTypeTraits {}; #define TYPE_TRAITS(FieldType, CType, WireFormatType, IsMessage, IsEnum) \ template <> \ - class MapFieldTypeTraits<FieldDescriptor::TYPE_##FieldType> { \ + class MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType> { \ public: \ typedef CType CppType; \ static const bool kIsMessage = IsMessage; \ @@ -243,7 +275,7 @@ class MapFieldTypeTraits {}; WireFormatLite::WIRETYPE_##WireFormatType; \ }; -TYPE_TRAITS(MESSAGE , Message, LENGTH_DELIMITED, true, false) +TYPE_TRAITS(MESSAGE , MessageLite, LENGTH_DELIMITED, true, false) TYPE_TRAITS(STRING , string , LENGTH_DELIMITED, false, false) TYPE_TRAITS(BYTES , string , LENGTH_DELIMITED, false, false) TYPE_TRAITS(INT64 , int64 , VARINT , false, false) @@ -263,51 +295,46 @@ TYPE_TRAITS(BOOL , bool , VARINT , false, false) #undef TYPE_TRAITS -// Handler for proto field type. Define types and constants used in compile -// time. Also define functions used in parsing and serializing. -template <FieldDescriptor::Type Type> -class MapProtoTypeHandler { +template <WireFormatLite::FieldType field_type> +class MapWireFieldTypeHandler { public: - // Internal stored type in MapEntry for given proto field type. - typedef typename MapFieldTypeTraits<Type>::CppType CppType; - - // Whether given type is a message. - static const bool kIsMessage = MapFieldTypeTraits<Type>::kIsMessage; - - // Whether given type is an enum. - static const bool kIsEnum = MapFieldTypeTraits<Type>::kIsEnum; - - // The wire type of given proto field type. + // Internal stored type in MapEntryLite for given wire field type. + typedef typename MapWireFieldTypeTraits<field_type>::CppType CppType; + // Corresponding wire type for field type. static const WireFormatLite::WireType kWireType = - MapFieldTypeTraits<Type>::kWireType; + MapWireFieldTypeTraits<field_type>::kWireType; + // Whether wire type is for message. + static const bool kIsMessage = MapWireFieldTypeTraits<field_type>::kIsMessage; + // Whether wire type is for enum. + static const bool kIsEnum = MapWireFieldTypeTraits<field_type>::kIsEnum; // Functions used in parsing and serialization. =================== - template <typename ValueType> static inline int ByteSize(const ValueType& value); template <typename ValueType> static inline int GetCachedSize(const ValueType& value); + template <typename ValueType> + static inline bool Read(io::CodedInputStream* input, ValueType* value); static inline void Write(int field, const CppType& value, io::CodedOutputStream* output); static inline uint8* WriteToArray(int field, const CppType& value, uint8* output); - template <typename ValueType> - static inline bool Read(io::CodedInputStream* input, ValueType* value); }; template <> template <typename ValueType> -inline int MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::ByteSize( +inline int MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::ByteSize( const ValueType& value) { return WireFormatLite::MessageSizeNoVirtual(value); } -#define BYTE_SIZE(FieldType, DeclaredType) \ - template <> \ - template <typename ValueType> \ - inline int MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::ByteSize( \ - const ValueType& value) { \ - return WireFormatLite::DeclaredType##Size(value); \ +#define BYTE_SIZE(FieldType, DeclaredType) \ + template <> \ + template <typename ValueType> \ + inline int \ + MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::ByteSize( \ + const ValueType& value) { \ + return WireFormatLite::DeclaredType##Size(value); \ } BYTE_SIZE(STRING, String) @@ -322,12 +349,13 @@ BYTE_SIZE(ENUM , Enum) #undef BYTE_SIZE -#define FIXED_BYTE_SIZE(FieldType, DeclaredType) \ - template <> \ - template <typename ValueType> \ - inline int MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::ByteSize( \ - const ValueType& value) { \ - return WireFormatLite::k##DeclaredType##Size; \ +#define FIXED_BYTE_SIZE(FieldType, DeclaredType) \ + template <> \ + template <typename ValueType> \ + inline int \ + MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::ByteSize( \ + const ValueType& value) { \ + return WireFormatLite::k##DeclaredType##Size; \ } FIXED_BYTE_SIZE(DOUBLE , Double) @@ -342,18 +370,18 @@ FIXED_BYTE_SIZE(BOOL , Bool) template <> template <typename ValueType> -inline int MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::GetCachedSize( - const ValueType& value) { +inline int MapWireFieldTypeHandler< + WireFormatLite::TYPE_MESSAGE>::GetCachedSize(const ValueType& value) { return WireFormatLite::LengthDelimitedSize(value.GetCachedSize()); } -#define GET_CACHED_SIZE(FieldType, DeclaredType) \ - template <> \ - template <typename ValueType> \ - inline int \ - MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::GetCachedSize( \ - const ValueType& value) { \ - return WireFormatLite::DeclaredType##Size(value); \ +#define GET_CACHED_SIZE(FieldType, DeclaredType) \ + template <> \ + template <typename ValueType> \ + inline int \ + MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::GetCachedSize( \ + const ValueType& value) { \ + return WireFormatLite::DeclaredType##Size(value); \ } GET_CACHED_SIZE(STRING, String) @@ -368,13 +396,13 @@ GET_CACHED_SIZE(ENUM , Enum) #undef GET_CACHED_SIZE -#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType) \ - template <> \ - template <typename ValueType> \ - inline int \ - MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::GetCachedSize( \ - const ValueType& value) { \ - return WireFormatLite::k##DeclaredType##Size; \ +#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType) \ + template <> \ + template <typename ValueType> \ + inline int \ + MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::GetCachedSize( \ + const ValueType& value) { \ + return WireFormatLite::k##DeclaredType##Size; \ } GET_FIXED_CACHED_SIZE(DOUBLE , Double) @@ -388,26 +416,28 @@ GET_FIXED_CACHED_SIZE(BOOL , Bool) #undef GET_FIXED_CACHED_SIZE template <> -inline void MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::Write( - int field, const Message& value, io::CodedOutputStream* output) { +inline void MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::Write( + int field, const MessageLite& value, io::CodedOutputStream* output) { WireFormatLite::WriteMessageMaybeToArray(field, value, output); } template <> -inline uint8* MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::WriteToArray( - int field, const Message& value, uint8* output) { +inline uint8* +MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::WriteToArray( + int field, const MessageLite& value, uint8* output) { return WireFormatLite::WriteMessageToArray(field, value, output); } #define WRITE_METHOD(FieldType, DeclaredType) \ template <> \ - inline void MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::Write( \ + inline void \ + MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::Write( \ int field, const CppType& value, io::CodedOutputStream* output) { \ return WireFormatLite::Write##DeclaredType(field, value, output); \ } \ template <> \ inline uint8* \ - MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::WriteToArray( \ + MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::WriteToArray( \ int field, const CppType& value, uint8* output) { \ return WireFormatLite::Write##DeclaredType##ToArray(field, value, output); \ } @@ -433,33 +463,33 @@ WRITE_METHOD(BOOL , Bool) template <> template <typename ValueType> -inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::Read( +inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::Read( io::CodedInputStream* input, ValueType* value) { return WireFormatLite::ReadMessageNoVirtual(input, value); } template <> template <typename ValueType> -inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_STRING>::Read( +inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_STRING>::Read( io::CodedInputStream* input, ValueType* value) { return WireFormatLite::ReadString(input, value); } template <> template <typename ValueType> -inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_BYTES>::Read( +inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_BYTES>::Read( io::CodedInputStream* input, ValueType* value) { return WireFormatLite::ReadBytes(input, value); } -#define READ_METHOD(FieldType) \ - template <> \ - template <typename ValueType> \ - inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::Read( \ - io::CodedInputStream* input, ValueType* value) { \ - return WireFormatLite::ReadPrimitive<CppType, \ - WireFormatLite::TYPE_##FieldType>( \ - input, value); \ +#define READ_METHOD(FieldType) \ + template <> \ + template <typename ValueType> \ + inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::Read( \ + io::CodedInputStream* input, ValueType* value) { \ + return WireFormatLite::ReadPrimitive<CppType, \ + WireFormatLite::TYPE_##FieldType>( \ + input, value); \ } READ_METHOD(INT64) diff --git a/src/google/protobuf/map_unittest.proto b/src/google/protobuf/map_unittest.proto index 54bc4486..830f672b 100644 --- a/src/google/protobuf/map_unittest.proto +++ b/src/google/protobuf/map_unittest.proto @@ -30,6 +30,7 @@ syntax = "proto3"; +option cc_enable_arenas = true; import "google/protobuf/unittest.proto"; @@ -59,6 +60,10 @@ message TestMap { map<int32 , ForeignMessage> map_int32_foreign_message = 17; } +message TestMapSubmessage { + optional TestMap test_map = 1; +} + message TestMessageMap { map<int32, TestAllTypes> map_int32_message = 1; } @@ -75,3 +80,26 @@ enum MapEnum { MAP_ENUM_BAR = 1; MAP_ENUM_BAZ = 2; } + +// Test embeded message with required fields +message TestRequiredMessageMap { + map<int32, TestRequired> map_field = 1; +} + +message TestArenaMap { + map<int32 , int32 > map_int32_int32 = 1; + map<int64 , int64 > map_int64_int64 = 2; + map<uint32 , uint32 > map_uint32_uint32 = 3; + map<uint64 , uint64 > map_uint64_uint64 = 4; + map<sint32 , sint32 > map_sint32_sint32 = 5; + map<sint64 , sint64 > map_sint64_sint64 = 6; + map<fixed32 , fixed32 > map_fixed32_fixed32 = 7; + map<fixed64 , fixed64 > map_fixed64_fixed64 = 8; + map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9; + map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10; + map<int32 , float > map_int32_float = 11; + map<int32 , double > map_int32_double = 12; + map<bool , bool > map_bool_bool = 13; + map<int32 , MapEnum > map_int32_enum = 14; + map<int32 , ForeignMessage> map_int32_foreign_message = 15; +} diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc index afe95461..f58be848 100644 --- a/src/google/protobuf/message.cc +++ b/src/google/protobuf/message.cc @@ -441,6 +441,30 @@ const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor( } namespace internal { +namespace { +void ShutdownRepeatedFieldAccessor() { + internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<int32> >::ShutDown(); + internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<uint32> >::ShutDown(); + internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<int64> >::ShutDown(); + internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<uint64> >::ShutDown(); + internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<float> >::ShutDown(); + internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<double> >::ShutDown(); + internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<bool> >::ShutDown(); + internal::Singleton<internal::RepeatedPtrFieldStringAccessor>::ShutDown(); + internal::Singleton<internal::RepeatedPtrFieldMessageAccessor>::ShutDown(); + internal::Singleton<internal::MapFieldAccessor>::ShutDown(); +} + +struct ShutdownRepeatedFieldRegister { + ShutdownRepeatedFieldRegister() { + OnShutdown(&ShutdownRepeatedFieldAccessor); + } +} shutdown_; + +} // namespace +} // namespace internal + +namespace internal { // Macro defined in repeated_field.h. We can only define the Message-specific // GenericTypeHandler specializations here because we depend on Message, which // is not part of proto2-lite hence is not available in repeated_field.h. diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index 1d8f2499..6e1929e5 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -208,7 +208,7 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite { // This is much, much slower than IsInitialized() as it is implemented // purely via reflection. Generally, you should not call this unless you // have already determined that an error exists by calling IsInitialized(). - void FindInitializationErrors(vector<string>* errors) const; + void FindInitializationErrors(std::vector<string>* errors) const; // Like FindInitializationErrors, but joins all the strings, delimited by // commas, and returns them. @@ -456,7 +456,7 @@ class LIBPROTOBUF_EXPORT Reflection { // Swap fields listed in fields vector of two messages. virtual void SwapFields(Message* message1, Message* message2, - const vector<const FieldDescriptor*>& fields) + const std::vector<const FieldDescriptor*>& fields) const = 0; // Swap two elements of a repeated field. @@ -470,8 +470,9 @@ class LIBPROTOBUF_EXPORT Reflection { // return true and repeated fields will only be listed if FieldSize(field) // would return non-zero. Fields (both normal fields and extension fields) // will be listed ordered by field number. - virtual void ListFields(const Message& message, - vector<const FieldDescriptor*>* output) const = 0; + virtual void ListFields( + const Message& message, + std::vector<const FieldDescriptor*>* output) const = 0; // Singular field getters ------------------------------------------ // These get the value of a non-repeated field. They return the default @@ -523,7 +524,7 @@ class LIBPROTOBUF_EXPORT Reflection { // regardless of the field's underlying representation. When initializing // a newly-constructed string, though, it's just as fast and more readable // to use code like: - // string str = reflection->GetString(field); + // string str = reflection->GetString(message, field); virtual const string& GetStringReference(const Message& message, const FieldDescriptor* field, string* scratch) const = 0; @@ -842,6 +843,19 @@ class LIBPROTOBUF_EXPORT Reflection { // } virtual bool SupportsUnknownEnumValues() const { return false; } + // Returns the MessageFactory associated with this message. This can be + // useful for determining if a message is a generated message or not, for + // example: + // + // if (message->GetReflection()->GetMessageFactory() == + // google::protobuf::MessageFactory::generated_factory()) { + // // This is a generated message. + // } + // + // It can also be used to create more messages of this type, though + // Message::New() is an easier way to accomplish this. + virtual MessageFactory* GetMessageFactory() const; + // --------------------------------------------------------------------------- protected: @@ -854,8 +868,6 @@ class LIBPROTOBUF_EXPORT Reflection { Message* message, const FieldDescriptor* field, FieldDescriptor::CppType, int ctype, const Descriptor* message_type) const = 0; - virtual MessageFactory* GetMessageFactory() const; - // The following methods are used to implement (Mutable)RepeatedFieldRef. // A Ref object will store a raw pointer to the repeated field data (obtained // from RepeatedFieldData()) and a pointer to a Accessor (obtained from @@ -967,6 +979,7 @@ const RepeatedField<TYPE>& Reflection::GetRepeatedField<TYPE>( \ const Message& message, const FieldDescriptor* field) const; \ \ template<> \ +LIBPROTOBUF_EXPORT \ RepeatedField<TYPE>* Reflection::MutableRepeatedField<TYPE>( \ Message* message, const FieldDescriptor* field) const; diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h index 106982cc..eab61c14 100644 --- a/src/google/protobuf/message_lite.h +++ b/src/google/protobuf/message_lite.h @@ -41,6 +41,7 @@ #include <google/protobuf/stubs/common.h> + namespace google { namespace protobuf { class Arena; @@ -133,9 +134,10 @@ class LIBPROTOBUF_EXPORT MessageLite { // just simple wrappers around MergeFromCodedStream(). Clear() will be called // before merging the input. - // Fill the message with a protocol buffer parsed from the given input - // stream. Returns false on a read error or if the input is in the - // wrong format. + // Fill the message with a protocol buffer parsed from the given input stream. + // Returns false on a read error or if the input is in the wrong format. A + // successful return does not indicate the entire input is consumed, ensure + // you call ConsumedEntireMessage() to check that if applicable. bool ParseFromCodedStream(io::CodedInputStream* input); // Like ParseFromCodedStream(), but accepts messages that are missing // required fields. @@ -154,7 +156,11 @@ class LIBPROTOBUF_EXPORT MessageLite { // missing required fields. bool ParsePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size); - // Parse a protocol buffer contained in a string. + // Parses a protocol buffer contained in a string. Returns true on success. + // This function takes a string in the (non-human-readable) binary wire + // format, matching the encoding output by MessageLite::SerializeToString(). + // If you'd like to convert a human-readable string into a protocol buffer + // object, see google::protobuf::TextFormat::ParseFromString(). bool ParseFromString(const string& data); // Like ParseFromString(), but accepts messages that are missing // required fields. diff --git a/src/google/protobuf/new_delete_capture.cc b/src/google/protobuf/new_delete_capture.cc deleted file mode 100644 index baf42ffe..00000000 --- a/src/google/protobuf/new_delete_capture.cc +++ /dev/null @@ -1,121 +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. - -// This file exists for testing allocation behavior when using arenas by hooking -// new/delete. It is a copy of //experimental/mvels/util/new_delete_capture.cc. - -#include <google/protobuf/new_delete_capture.h> - -#include <pthread.h> - -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/malloc_hook.h> -#include <google/protobuf/stubs/spinlock.h> - -namespace google { -namespace { - -pthread_t gthread; -protobuf_unittest::NewDeleteCapture *ghooked_instance = NULL; -SpinLock gspinlock(base::LINKER_INITIALIZED); - -} // namespace - -namespace protobuf_unittest { - -NewDeleteCapture::NewDeleteCapture() - : alloc_count_(0), - alloc_size_(0), - alloc_ptr_(NULL), - free_count_(0), - free_ptr_(NULL) {} - -NewDeleteCapture::~NewDeleteCapture() { Unhook(); } - -void NewDeleteCapture::Reset() { - alloc_count_ = 0; - alloc_size_ = 0; - free_count_ = 0; - alloc_ptr_ = NULL; - free_ptr_ = NULL; -} - -bool NewDeleteCapture::Hook(bool reset) { - SpinLockHolder spinlock(&gspinlock); - if (ghooked_instance != this) { - GOOGLE_CHECK(ghooked_instance == NULL) - << " NewDeleteCapture can have only 1 active instance"; - GOOGLE_CHECK(MallocHook::AddNewHook(NewHook)); - GOOGLE_CHECK(MallocHook::AddDeleteHook(DeleteHook)); - gthread = pthread_self(); - ghooked_instance = this; - if (reset) { - Reset(); - } - return true; - } - return false; -} - -bool NewDeleteCapture::Unhook() { - SpinLockHolder spinlock(&gspinlock); - if (ghooked_instance == this) { - gthread = pthread_t(); - ghooked_instance = NULL; - GOOGLE_CHECK(MallocHook::RemoveDeleteHook(DeleteHook)); - GOOGLE_CHECK(MallocHook::RemoveNewHook(NewHook)); - return true; - } - return false; -} - -void NewDeleteCapture::NewHook(const void *ptr, size_t size) { - SpinLockHolder spinlock(&gspinlock); - if (gthread == pthread_self()) { - auto &rthis = *ghooked_instance; - if (++rthis.alloc_count_ == 1) { - rthis.alloc_size_ = size; - rthis.alloc_ptr_ = ptr; - } - } -} - -void NewDeleteCapture::DeleteHook(const void *ptr) { - SpinLockHolder spinlock(&gspinlock); - if (gthread == pthread_self()) { - auto &rthis = *ghooked_instance; - if (++rthis.free_count_ == 1) { - rthis.free_ptr_ = ptr; - } - } -} - -} // namespace protobuf_unittest -} // namespace google diff --git a/src/google/protobuf/new_delete_capture.h b/src/google/protobuf/new_delete_capture.h deleted file mode 100644 index 4ab550cd..00000000 --- a/src/google/protobuf/new_delete_capture.h +++ /dev/null @@ -1,175 +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. - -// This file exists for testing allocation behavior when using arenas by hooking -// new/delete. It is a copy of //experimental/mvels/util/new_delete_capture.h. -// -// Copyright 2014 Google Inc. -// -// Author: Martijn Vels -// -// A simple class that captures memory allocations and deletes. -// -// This class is private to //strings and only intended to be used inside -// unit tests. It uses the MallocHook functionality to capture memory -// allocation and delete operations performed by the thread that activated -// a hook on a specific instance. -// -// The class captures the following information: -// - Total allocation count (new, malloc(), etc). -// - Total delete count (delete, free(), etc). -// - The size and returned pointer for the first memory allocation. -// - The pointer for the first delete operation. -// -// The latter 2 infos (size and pointer of first new/delete) are usefull in -// cases where you can closely scope a Hook() / Unhook sequence around a -// specific piece of code where you expect no more than 1 pair of new / delete -// operations. -// -// Sample usage where we expect a single unique alloc / free: -// -// NewDeleteCapture capture_alloc; -// const void *ptr; -// { -// capture_alloc.Hook(); -// MyAllocationClass my_instance(size); -// capture_alloc.Unhook(); -// -// ptr = my_instance.ptr(); -// GOOGLE_CHECK_EQ(1, capture_alloc.alloc_count()); -// GOOGLE_CHECK_EQ(0, capture_alloc.free_count()); -// GOOGLE_CHECK_EQ(size, capture_alloc.alloc_size()); -// GOOGLE_CHECK_EQ(ptr, capture_alloc.alloc_ptr()); -// -// capture_alloc.Hook(); -// } -// capture_alloc.Unhook(); -// GOOGLE_CHECK_EQ(1, capture_alloc.alloc_count()); -// GOOGLE_CHECK_EQ(1, capture_alloc.free_count()); -// GOOGLE_CHECK_EQ(ptr, capture_alloc.free_ptr()); -// -// You can only have one NewDeleteCapture instance active at the time. It is -// total valid to have many instances in different threads, but only one -// instance can have a hook active. -// -// Legal: -// -// NewDeleteCapture capture_alloc1; -// NewDeleteCapture capture_alloc2; -// const void *ptr; -// { -// capture_alloc1.Hook(); -// MyAllocationClass my_instance(size); -// capture_alloc1.Unhook(); -// -// capture_alloc2.Hook(); -// my_instance.reset(size); -// capture_alloc2.Unhook(); -// } -// -// Illegal: -// -// NewDeleteCapture capture_alloc1; -// NewDeleteCapture capture_alloc2; -// const void *ptr; -// { -// capture_alloc1.Hook(); -// MyAllocationClass my_instance(size); -// -// capture_alloc2.Hook(); -// my_instance.reset(size); -// -// capture_alloc1.Unhook(); -// capture_alloc2.Unhook(); -// } -// -#ifndef GOOGLE_PROTOBUF_NEW_DELETE_CAPTURE_H__ -#define GOOGLE_PROTOBUF_NEW_DELETE_CAPTURE_H__ - -#include <stddef.h> - -namespace google { -namespace protobuf_unittest { - -class NewDeleteCapture { - public: - // Creates a new inactive capture instance - NewDeleteCapture(); - - // Destroys this capture instance. Active hooks are automatically removed. - ~NewDeleteCapture(); - - // Activates a hook on this instance. If reset is true (the default), all - // internal counters will be reset to 0. - // Returns true if the hook was activated, false if this instance already - // owned the hook. - // Requires no other instance owning the hook (check fails) - bool Hook(bool reset = true); - - // De-activate the hook on this instance. - // Returns true if the hook was removed, false if this instance did not own - // the hook. - bool Unhook(); - - // Resets all counters to 0 - void Reset(); - - // Returns the total number of allocations (new, malloc(), etc) - size_t alloc_count() const { return alloc_count_; } - - // Returns the total number of deletes (delete, free(), etc) - size_t free_count() const { return free_count_; } - - // Returns the size of the first observed allocation - size_t alloc_size() const { return alloc_size_; } - - // Returns the allocated ptr of the first observed allocation - const void *alloc_ptr() const { return alloc_ptr_; } - - // Returns the ptr of the first observed delete - const void* free_ptr() const { return free_ptr_; } - - private: - static void NewHook(const void *ptr, size_t size); - static void DeleteHook(const void *ptr); - - private: - size_t alloc_count_; - size_t alloc_size_; - const void *alloc_ptr_; - - size_t free_count_; - const void *free_ptr_; -}; - -} // namespace protobuf_unittest - -} // namespace google -#endif // GOOGLE_PROTOBUF_NEW_DELETE_CAPTURE_H__ diff --git a/src/google/protobuf/no_field_presence_test.cc b/src/google/protobuf/no_field_presence_test.cc index f248327c..4b7b31d9 100644 --- a/src/google/protobuf/no_field_presence_test.cc +++ b/src/google/protobuf/no_field_presence_test.cc @@ -269,6 +269,10 @@ TEST(NoFieldPresenceTest, MessageFieldPresenceTest) { EXPECT_EQ(true, message.has_optional_lazy_message()); message.clear_optional_lazy_message(); EXPECT_EQ(false, message.has_optional_lazy_message()); + + // Test field presence of a message field on the default instance. + EXPECT_EQ(false, proto2_nofieldpresence_unittest::TestAllTypes:: + default_instance().has_optional_nested_message()); } TEST(NoFieldPresenceTest, ReflectionHasFieldTest) { @@ -287,6 +291,13 @@ TEST(NoFieldPresenceTest, ReflectionHasFieldTest) { EXPECT_EQ(false, r->HasField(message, field)); } + // Test field presence of a message field on the default instance. + const google::protobuf::FieldDescriptor* msg_field = + desc->FindFieldByName("optional_nested_message"); + EXPECT_EQ(false, r->HasField( + proto2_nofieldpresence_unittest::TestAllTypes:: + default_instance(), msg_field)); + // Fill all fields, expect everything to report true (check oneofs below). FillValues(&message); for (int i = 0; i < desc->field_count(); i++) { diff --git a/src/google/protobuf/preserve_unknown_enum_test.cc b/src/google/protobuf/preserve_unknown_enum_test.cc index 33e9ea10..9f8703ae 100644 --- a/src/google/protobuf/preserve_unknown_enum_test.cc +++ b/src/google/protobuf/preserve_unknown_enum_test.cc @@ -30,6 +30,7 @@ #include <google/protobuf/unittest.pb.h> #include <google/protobuf/unittest_preserve_unknown_enum.pb.h> +#include <google/protobuf/unittest_preserve_unknown_enum2.pb.h> #include <google/protobuf/dynamic_message.h> #include <google/protobuf/descriptor.h> #include <gtest/gtest.h> @@ -39,46 +40,55 @@ namespace protobuf { namespace { void FillMessage( - proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra* message) { + proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra* message) { message->set_e( - proto2_preserve_unknown_enum_unittest::E_EXTRA); + proto3_preserve_unknown_enum_unittest::E_EXTRA); message->add_repeated_e( - proto2_preserve_unknown_enum_unittest::E_EXTRA); + proto3_preserve_unknown_enum_unittest::E_EXTRA); message->add_repeated_packed_e( - proto2_preserve_unknown_enum_unittest::E_EXTRA); + proto3_preserve_unknown_enum_unittest::E_EXTRA); + message->add_repeated_packed_unexpected_e( + proto3_preserve_unknown_enum_unittest::E_EXTRA); message->set_oneof_e_1( - proto2_preserve_unknown_enum_unittest::E_EXTRA); + proto3_preserve_unknown_enum_unittest::E_EXTRA); } void CheckMessage( - const proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra& message) { - EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA, + const proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra& message) { + EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA, message.e()); EXPECT_EQ(1, message.repeated_e_size()); - EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA, + EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA, message.repeated_e(0)); EXPECT_EQ(1, message.repeated_packed_e_size()); - EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA, + EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA, message.repeated_packed_e(0)); - EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA, + EXPECT_EQ(1, message.repeated_packed_unexpected_e_size()); + EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA, + message.repeated_packed_unexpected_e(0)); + EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA, message.oneof_e_1()); } void CheckMessage( - const proto2_preserve_unknown_enum_unittest::MyMessage& message) { + const proto3_preserve_unknown_enum_unittest::MyMessage& message) { EXPECT_EQ(static_cast<int>( - proto2_preserve_unknown_enum_unittest::E_EXTRA), + proto3_preserve_unknown_enum_unittest::E_EXTRA), static_cast<int>(message.e())); EXPECT_EQ(1, message.repeated_e_size()); EXPECT_EQ(static_cast<int>( - proto2_preserve_unknown_enum_unittest::E_EXTRA), + proto3_preserve_unknown_enum_unittest::E_EXTRA), static_cast<int>(message.repeated_e(0))); EXPECT_EQ(1, message.repeated_packed_e_size()); EXPECT_EQ(static_cast<int>( - proto2_preserve_unknown_enum_unittest::E_EXTRA), + proto3_preserve_unknown_enum_unittest::E_EXTRA), static_cast<int>(message.repeated_packed_e(0))); + EXPECT_EQ(1, message.repeated_packed_unexpected_e_size()); EXPECT_EQ(static_cast<int>( - proto2_preserve_unknown_enum_unittest::E_EXTRA), + proto3_preserve_unknown_enum_unittest::E_EXTRA), + static_cast<int>(message.repeated_packed_unexpected_e(0))); + EXPECT_EQ(static_cast<int>( + proto3_preserve_unknown_enum_unittest::E_EXTRA), static_cast<int>(message.oneof_e_1())); } @@ -87,12 +97,12 @@ void CheckMessage( // Test that parsing preserves an unknown value in the enum field and does not // punt it to the UnknownFieldSet. TEST(PreserveUnknownEnumTest, PreserveParseAndSerialize) { - proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; + proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; FillMessage(&orig_message); string serialized; orig_message.SerializeToString(&serialized); - proto2_preserve_unknown_enum_unittest::MyMessage message; + proto3_preserve_unknown_enum_unittest::MyMessage message; EXPECT_EQ(true, message.ParseFromString(serialized)); CheckMessage(message); @@ -105,13 +115,13 @@ TEST(PreserveUnknownEnumTest, PreserveParseAndSerialize) { // Test that reflection based implementation also keeps unknown enum values and // doesn't put them into UnknownFieldSet. TEST(PreserveUnknownEnumTest, PreserveParseAndSerializeDynamicMessage) { - proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; + proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; FillMessage(&orig_message); string serialized = orig_message.SerializeAsString(); google::protobuf::DynamicMessageFactory factory; google::protobuf::scoped_ptr<google::protobuf::Message> message(factory.GetPrototype( - proto2_preserve_unknown_enum_unittest::MyMessage::descriptor())->New()); + proto3_preserve_unknown_enum_unittest::MyMessage::descriptor())->New()); EXPECT_EQ(true, message->ParseFromString(serialized)); message->DiscardUnknownFields(); @@ -120,14 +130,61 @@ TEST(PreserveUnknownEnumTest, PreserveParseAndSerializeDynamicMessage) { CheckMessage(orig_message); } +// Test that for proto2 messages, unknown values are in unknown fields. +TEST(PreserveUnknownEnumTest, Proto2HidesUnknownValues) { + proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; + FillMessage(&orig_message); + + string serialized; + orig_message.SerializeToString(&serialized); + + proto2_preserve_unknown_enum_unittest::MyMessage message; + EXPECT_EQ(true, message.ParseFromString(serialized)); + // The intermediate message has everything in its "unknown fields". + proto2_preserve_unknown_enum_unittest::MyMessage message2 = message; + message2.DiscardUnknownFields(); + EXPECT_EQ(0, message2.ByteSize()); + + // But when we pass it to the correct structure, all values are there. + serialized.clear(); + message.SerializeToString(&serialized); + EXPECT_EQ(true, orig_message.ParseFromString(serialized)); + CheckMessage(orig_message); +} + +// Same as before, for a dynamic message. +TEST(PreserveUnknownEnumTest, DynamicProto2HidesUnknownValues) { + proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; + FillMessage(&orig_message); + + string serialized; + orig_message.SerializeToString(&serialized); + + google::protobuf::DynamicMessageFactory factory; + google::protobuf::scoped_ptr<google::protobuf::Message> message(factory.GetPrototype( + proto2_preserve_unknown_enum_unittest::MyMessage::descriptor())->New()); + EXPECT_EQ(true, message->ParseFromString(serialized)); + // The intermediate message has everything in its "unknown fields". + proto2_preserve_unknown_enum_unittest::MyMessage message2; + message2.CopyFrom(*message); + message2.DiscardUnknownFields(); + EXPECT_EQ(0, message2.ByteSize()); + + // But when we pass it to the correct structure, all values are there. + serialized.clear(); + message->SerializeToString(&serialized); + EXPECT_EQ(true, orig_message.ParseFromString(serialized)); + CheckMessage(orig_message); +} + // Test that reflection provides EnumValueDescriptors for unknown values. TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) { - proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; + proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; FillMessage(&orig_message); string serialized; orig_message.SerializeToString(&serialized); - proto2_preserve_unknown_enum_unittest::MyMessage message; + proto3_preserve_unknown_enum_unittest::MyMessage message; EXPECT_EQ(true, message.ParseFromString(serialized)); CheckMessage(message); @@ -138,7 +195,7 @@ TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) { // This should dynamically create an EnumValueDescriptor. const google::protobuf::EnumValueDescriptor* enum_value = r->GetEnum(message, field); EXPECT_EQ(enum_value->number(), - static_cast<int>(proto2_preserve_unknown_enum_unittest::E_EXTRA)); + static_cast<int>(proto3_preserve_unknown_enum_unittest::E_EXTRA)); // Fetching value for a second time should return the same pointer. const google::protobuf::EnumValueDescriptor* enum_value_second = @@ -150,7 +207,7 @@ TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) { d->FindFieldByName("repeated_e"); enum_value = r->GetRepeatedEnum(message, repeated_field, 0); EXPECT_EQ(enum_value->number(), - static_cast<int>(proto2_preserve_unknown_enum_unittest::E_EXTRA)); + static_cast<int>(proto3_preserve_unknown_enum_unittest::E_EXTRA)); // Should reuse the same EnumValueDescriptor, even for a different field. EXPECT_EQ(enum_value, enum_value_second); @@ -164,7 +221,7 @@ TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) { // Test that the new integer-based enum reflection API works. TEST(PreserveUnknownEnumTest, IntegerEnumReflectionAPI) { - proto2_preserve_unknown_enum_unittest::MyMessage message; + proto3_preserve_unknown_enum_unittest::MyMessage message; const google::protobuf::Reflection* r = message.GetReflection(); const google::protobuf::Descriptor* d = message.GetDescriptor(); @@ -200,6 +257,7 @@ TEST(PreserveUnknownEnumTest, Proto2CatchesUnknownValues) { EXPECT_TRUE(enum_value != NULL); r->AddEnum(&message, repeated_field, enum_value); +#ifdef PROTOBUF_HAS_DEATH_TEST // Enum-field integer-based setters GOOGLE_DCHECK-fail on invalid values, in order to // remain consistent with proto2 generated code. EXPECT_DEBUG_DEATH({ @@ -214,11 +272,12 @@ TEST(PreserveUnknownEnumTest, Proto2CatchesUnknownValues) { r->AddEnumValue(&message, repeated_field, 4242); r->GetRepeatedEnum(message, repeated_field, 1); }, "AddEnumValue accepts only valid integer values"); +#endif // PROTOBUF_HAS_DEATH_TEST } TEST(PreserveUnknownEnumTest, SupportsUnknownEnumValuesAPI) { protobuf_unittest::TestAllTypes proto2_message; - proto2_preserve_unknown_enum_unittest::MyMessage new_message; + proto3_preserve_unknown_enum_unittest::MyMessage new_message; const google::protobuf::Reflection* proto2_reflection = proto2_message.GetReflection(); const google::protobuf::Reflection* new_reflection = new_message.GetReflection(); diff --git a/src/google/protobuf/reflection.h b/src/google/protobuf/reflection.h index 17d89a18..03c761c1 100644..100755 --- a/src/google/protobuf/reflection.h +++ b/src/google/protobuf/reflection.h @@ -33,6 +33,11 @@ #ifndef GOOGLE_PROTOBUF_REFLECTION_H__ #define GOOGLE_PROTOBUF_REFLECTION_H__ +#include <memory> +#ifndef _SHARED_PTR_H +#include <google/protobuf/stubs/shared_ptr.h> +#endif + #include <google/protobuf/message.h> namespace google { @@ -223,7 +228,7 @@ class RepeatedFieldRef< const Message* default_instance_; }; -// MutableRepeatedFieldRef definition for non-message types. +// MutableRepeatedFieldRef definition for message types. template<typename T> class MutableRepeatedFieldRef< T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> { @@ -297,10 +302,298 @@ class MutableRepeatedFieldRef< const AccessorType* accessor_; const Message* default_instance_; }; + +namespace internal { +// Interfaces used to implement reflection RepeatedFieldRef API. +// Reflection::GetRepeatedAccessor() should return a pointer to an singleton +// object that implements the below interface. +// +// This interface passes/returns values using void pointers. The actual type +// of the value depends on the field's cpp_type. Following is a mapping from +// cpp_type to the type that should be used in this interface: +// +// field->cpp_type() T Actual type of void* +// CPPTYPE_INT32 int32 int32 +// CPPTYPE_UINT32 uint32 uint32 +// CPPTYPE_INT64 int64 int64 +// CPPTYPE_UINT64 uint64 uint64 +// CPPTYPE_DOUBLE double double +// CPPTYPE_FLOAT float float +// CPPTYPE_BOOL bool bool +// CPPTYPE_ENUM generated enum type int32 +// CPPTYPE_STRING string string +// CPPTYPE_MESSAGE generated message type google::protobuf::Message +// or google::protobuf::Message +// +// Note that for enums we use int32 in the interface. +// +// You can map from T to the actual type using RefTypeTraits: +// typedef RefTypeTraits<T>::AccessorValueType ActualType; +class LIBPROTOBUF_EXPORT RepeatedFieldAccessor { + public: + // Typedefs for clarity. + typedef void Field; + typedef void Value; + typedef void Iterator; + + virtual ~RepeatedFieldAccessor(); + virtual bool IsEmpty(const Field* data) const = 0; + virtual int Size(const Field* data) const = 0; + // Depends on the underlying representation of the repeated field, this + // method can return a pointer to the underlying object if such an object + // exists, or fill the data into scratch_space and return scratch_space. + // Callers of this method must ensure scratch_space is a valid pointer + // to a mutable object of the correct type. + virtual const Value* Get( + const Field* data, int index, Value* scratch_space) const = 0; + + virtual void Clear(Field* data) const = 0; + virtual void Set(Field* data, int index, const Value* value) const = 0; + virtual void Add(Field* data, const Value* value) const = 0; + virtual void RemoveLast(Field* data) const = 0; + virtual void SwapElements(Field* data, int index1, int index2) const = 0; + virtual void Swap(Field* data, const RepeatedFieldAccessor* other_mutator, + Field* other_data) const = 0; + + // Create an iterator that points at the begining of the repeated field. + virtual Iterator* BeginIterator(const Field* data) const = 0; + // Create an iterator that points at the end of the repeated field. + virtual Iterator* EndIterator(const Field* data) const = 0; + // Make a copy of an iterator and return the new copy. + virtual Iterator* CopyIterator(const Field* data, + const Iterator* iterator) const = 0; + // Move an iterator to point to the next element. + virtual Iterator* AdvanceIterator(const Field* data, + Iterator* iterator) const = 0; + // Compare whether two iterators point to the same element. + virtual bool EqualsIterator(const Field* data, const Iterator* a, + const Iterator* b) const = 0; + // Delete an iterator created by BeginIterator(), EndIterator() and + // CopyIterator(). + virtual void DeleteIterator(const Field* data, Iterator* iterator) const = 0; + // Like Get() but for iterators. + virtual const Value* GetIteratorValue(const Field* data, + const Iterator* iterator, + Value* scratch_space) const = 0; + + // Templated methods that make using this interface easier for non-message + // types. + template<typename T> + T Get(const Field* data, int index) const { + typedef typename RefTypeTraits<T>::AccessorValueType ActualType; + ActualType scratch_space; + return static_cast<T>( + *reinterpret_cast<const ActualType*>( + Get(data, index, static_cast<Value*>(&scratch_space)))); + } + + template<typename T, typename ValueType> + void Set(Field* data, int index, const ValueType& value) const { + typedef typename RefTypeTraits<T>::AccessorValueType ActualType; + // In this RepeatedFieldAccessor interface we pass/return data using + // raw pointers. Type of the data these raw pointers point to should + // be ActualType. Here we have a ValueType object and want a ActualType + // pointer. We can't cast a ValueType pointer to an ActualType pointer + // directly because their type might be different (for enums ValueType + // may be a generated enum type while ActualType is int32). To be safe + // we make a copy to get a temporary ActualType object and use it. + ActualType tmp = static_cast<ActualType>(value); + Set(data, index, static_cast<const Value*>(&tmp)); + } + + template<typename T, typename ValueType> + void Add(Field* data, const ValueType& value) const { + typedef typename RefTypeTraits<T>::AccessorValueType ActualType; + // In this RepeatedFieldAccessor interface we pass/return data using + // raw pointers. Type of the data these raw pointers point to should + // be ActualType. Here we have a ValueType object and want a ActualType + // pointer. We can't cast a ValueType pointer to an ActualType pointer + // directly because their type might be different (for enums ValueType + // may be a generated enum type while ActualType is int32). To be safe + // we make a copy to get a temporary ActualType object and use it. + ActualType tmp = static_cast<ActualType>(value); + Add(data, static_cast<const Value*>(&tmp)); + } +}; + +// Implement (Mutable)RepeatedFieldRef::iterator +template<typename T> +class RepeatedFieldRefIterator + : public std::iterator<std::forward_iterator_tag, T> { + typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType; + typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType; + typedef typename RefTypeTraits<T>::IteratorPointerType IteratorPointerType; + + public: + // Constructor for non-message fields. + RepeatedFieldRefIterator(const void* data, + const RepeatedFieldAccessor* accessor, + bool begin) + : data_(data), accessor_(accessor), + iterator_(begin ? accessor->BeginIterator(data) : + accessor->EndIterator(data)), + scratch_space_(new AccessorValueType) { + } + // Constructor for message fields. + RepeatedFieldRefIterator(const void* data, + const RepeatedFieldAccessor* accessor, + bool begin, + AccessorValueType* scratch_space) + : data_(data), accessor_(accessor), + iterator_(begin ? accessor->BeginIterator(data) : + accessor->EndIterator(data)), + scratch_space_(scratch_space) { + } + ~RepeatedFieldRefIterator() { + accessor_->DeleteIterator(data_, iterator_); + } + RepeatedFieldRefIterator operator++(int) { + RepeatedFieldRefIterator tmp(*this); + iterator_ = accessor_->AdvanceIterator(data_, iterator_); + return tmp; + } + RepeatedFieldRefIterator& operator++() { + iterator_ = accessor_->AdvanceIterator(data_, iterator_); + return *this; + } + IteratorValueType operator*() const { + return static_cast<IteratorValueType>( + *static_cast<const AccessorValueType*>( + accessor_->GetIteratorValue( + data_, iterator_, scratch_space_.get()))); + } + IteratorPointerType operator->() const { + return static_cast<IteratorPointerType>( + accessor_->GetIteratorValue( + data_, iterator_, scratch_space_.get())); + } + bool operator!=(const RepeatedFieldRefIterator& other) const { + assert(data_ == other.data_); + assert(accessor_ == other.accessor_); + return !accessor_->EqualsIterator(data_, iterator_, other.iterator_); + } + bool operator==(const RepeatedFieldRefIterator& other) const { + return !this->operator!=(other); + } + + RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other) + : data_(other.data_), accessor_(other.accessor_), + iterator_(accessor_->CopyIterator(data_, other.iterator_)) { + } + RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) { + if (this != &other) { + accessor_->DeleteIterator(data_, iterator_); + data_ = other.data_; + accessor_ = other.accessor_; + iterator_ = accessor_->CopyIterator(data_, other.iterator_); + } + return *this; + } + + protected: + const void* data_; + const RepeatedFieldAccessor* accessor_; + void* iterator_; + google::protobuf::scoped_ptr<AccessorValueType> scratch_space_; +}; + +// TypeTraits that maps the type parameter T of RepeatedFieldRef or +// MutableRepeatedFieldRef to corresponding iterator type, +// RepeatedFieldAccessor type, etc. +template<typename T> +struct PrimitiveTraits { + static const bool is_primitive = false; +}; +#define DEFINE_PRIMITIVE(TYPE, type) \ + template<> struct PrimitiveTraits<type> { \ + static const bool is_primitive = true; \ + static const FieldDescriptor::CppType cpp_type = \ + FieldDescriptor::CPPTYPE_ ## TYPE; \ + }; +DEFINE_PRIMITIVE(INT32, int32) +DEFINE_PRIMITIVE(UINT32, uint32) +DEFINE_PRIMITIVE(INT64, int64) +DEFINE_PRIMITIVE(UINT64, uint64) +DEFINE_PRIMITIVE(FLOAT, float) +DEFINE_PRIMITIVE(DOUBLE, double) +DEFINE_PRIMITIVE(BOOL, bool) +#undef DEFINE_PRIMITIVE + +template<typename T> +struct RefTypeTraits< + T, typename internal::enable_if<PrimitiveTraits<T>::is_primitive>::type> { + typedef RepeatedFieldRefIterator<T> iterator; + typedef RepeatedFieldAccessor AccessorType; + typedef T AccessorValueType; + typedef T IteratorValueType; + typedef T* IteratorPointerType; + static const FieldDescriptor::CppType cpp_type = + PrimitiveTraits<T>::cpp_type; + static const Descriptor* GetMessageFieldDescriptor() { + return NULL; + } +}; + +template<typename T> +struct RefTypeTraits< + T, typename internal::enable_if<is_proto_enum<T>::value>::type> { + typedef RepeatedFieldRefIterator<T> iterator; + typedef RepeatedFieldAccessor AccessorType; + // We use int32 for repeated enums in RepeatedFieldAccessor. + typedef int32 AccessorValueType; + typedef T IteratorValueType; + typedef int32* IteratorPointerType; + static const FieldDescriptor::CppType cpp_type = + FieldDescriptor::CPPTYPE_ENUM; + static const Descriptor* GetMessageFieldDescriptor() { + return NULL; + } +}; + +template<typename T> +struct RefTypeTraits< + T, typename internal::enable_if<internal::is_same<string, T>::value>::type> { + typedef RepeatedFieldRefIterator<T> iterator; + typedef RepeatedFieldAccessor AccessorType; + typedef string AccessorValueType; + typedef string IteratorValueType; + typedef string* IteratorPointerType; + static const FieldDescriptor::CppType cpp_type = + FieldDescriptor::CPPTYPE_STRING; + static const Descriptor* GetMessageFieldDescriptor() { + return NULL; + } +}; + +template<typename T> +struct MessageDescriptorGetter { + static const Descriptor* get() { + return T::default_instance().GetDescriptor(); + } +}; +template<> +struct MessageDescriptorGetter<Message> { + static const Descriptor* get() { + return NULL; + } +}; + +template<typename T> +struct RefTypeTraits< + T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> { + typedef RepeatedFieldRefIterator<T> iterator; + typedef RepeatedFieldAccessor AccessorType; + typedef Message AccessorValueType; + typedef const T& IteratorValueType; + typedef const T* IteratorPointerType; + static const FieldDescriptor::CppType cpp_type = + FieldDescriptor::CPPTYPE_MESSAGE; + static const Descriptor* GetMessageFieldDescriptor() { + return MessageDescriptorGetter<T>::get(); + } +}; +} // namespace internal } // namespace protobuf } // namespace google -// Implementation details for (Mutable)RepeatedFieldRef. -#include <google/protobuf/repeated_field_reflection.h> - #endif // GOOGLE_PROTOBUF_REFLECTION_H__ diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index e14dcc62..f5f5d3f4 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -236,10 +236,11 @@ class RepeatedField { Arena* arena; Element elements[1]; }; - // Why not sizeof(Rep) - sizeof(Element)? Because this is not accurate w.r.t. - // trailing padding on the struct -- e.g. if Element is int, this would yield - // 12 on x86-64, not 8 as we want. - static const size_t kRepHeaderSize = sizeof(Arena*); + // We can not use sizeof(Rep) - sizeof(Element) due to the trailing padding on + // the struct. We can not use sizeof(Arena*) as well because there might be + // a "gap" after the field arena and before the field elements (e.g., when + // Element is double and pointer is 32bit). + static const size_t kRepHeaderSize; // Contains arena ptr and the elements array. We also keep the invariant that // if rep_ is NULL, then arena is NULL. Rep* rep_; @@ -263,6 +264,10 @@ class RepeatedField { } }; +template<typename Element> +const size_t RepeatedField<Element>::kRepHeaderSize = + reinterpret_cast<size_t>(&reinterpret_cast<Rep*>(16)->elements[0]) - 16; + namespace internal { template <typename It> class RepeatedPtrIterator; template <typename It, typename VoidPtr> class RepeatedPtrOverPtrsIterator; @@ -2259,7 +2264,7 @@ RepeatedPtrField<Element>::pointer_end() const { // Iterators and helper functions that follow the spirit of the STL // std::back_insert_iterator and std::back_inserter but are tailor-made -// for RepeatedField and RepatedPtrField. Typical usage would be: +// for RepeatedField and RepeatedPtrField. Typical usage would be: // // std::copy(some_sequence.begin(), some_sequence.end(), // google::protobuf::RepeatedFieldBackInserter(proto.mutable_sequence())); diff --git a/src/google/protobuf/repeated_field_reflection.h b/src/google/protobuf/repeated_field_reflection.h index 42f7be20..44d14d5b 100644 --- a/src/google/protobuf/repeated_field_reflection.h +++ b/src/google/protobuf/repeated_field_reflection.h @@ -38,6 +38,8 @@ #include <google/protobuf/stubs/shared_ptr.h> #endif +#include <google/protobuf/generated_enum_reflection.h> + namespace google { namespace protobuf { namespace internal { @@ -273,7 +275,7 @@ struct RefTypeTraits< template<typename T> struct RefTypeTraits< - T, typename internal::enable_if<internal::is_enum<T>::value>::type> { + T, typename internal::enable_if<is_proto_enum<T>::value>::type> { typedef RepeatedFieldRefIterator<T> iterator; typedef RepeatedFieldAccessor AccessorType; // We use int32 for repeated enums in RepeatedFieldAccessor. diff --git a/src/google/protobuf/repeated_field_reflection_unittest.cc b/src/google/protobuf/repeated_field_reflection_unittest.cc index ae43dfab..fcebe5ce 100644 --- a/src/google/protobuf/repeated_field_reflection_unittest.cc +++ b/src/google/protobuf/repeated_field_reflection_unittest.cc @@ -196,8 +196,7 @@ void TestRepeatedFieldRefIterator( int index = 0; for (typename Ref::const_iterator it = handle.begin(); it != handle.end(); ++it) { - ValueType value = static_cast<ValueType>(*it); - EXPECT_EQ((message.*GetFunc)(index), value); + EXPECT_EQ((message.*GetFunc)(index), *it); ++index; } EXPECT_EQ(handle.size(), index); @@ -410,6 +409,8 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForRegularFields) { EXPECT_TRUE(rf_message.empty()); EXPECT_TRUE(mrf_message.empty()); +#ifdef PROTOBUF_HAS_DEATH_TEST + // Make sure types are checked correctly at runtime. const FieldDescriptor* fd_optional_int32 = desc->FindFieldByName("optional_int32"); @@ -419,6 +420,8 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForRegularFields) { message, fd_repeated_int32), ""); EXPECT_DEATH(refl->GetRepeatedFieldRef<TestAllTypes>( message, fd_repeated_foreign_message), ""); + +#endif // PROTOBUF_HAS_DEATH_TEST } TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForEnums) { diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc index 9942af50..66e74523 100644 --- a/src/google/protobuf/repeated_field_unittest.cc +++ b/src/google/protobuf/repeated_field_unittest.cc @@ -92,8 +92,8 @@ TEST(RepeatedField, Small) { EXPECT_TRUE(field.empty()); EXPECT_EQ(field.size(), 0); - // Additional 8 bytes are for 'struct Rep' header. - int expected_usage = 4 * sizeof(int) + 8; + // Additional bytes are for 'struct Rep' header. + int expected_usage = 4 * sizeof(int) + sizeof(Arena*); EXPECT_EQ(field.SpaceUsedExcludingSelf(), expected_usage); } @@ -1131,7 +1131,7 @@ TEST_F(RepeatedPtrFieldIteratorTest, STLAlgorithms_lower_bound) { string v = "f"; RepeatedPtrField<string>::const_iterator it = - lower_bound(proto_array_.begin(), proto_array_.end(), v); + std::lower_bound(proto_array_.begin(), proto_array_.end(), v); EXPECT_EQ(*it, "n"); EXPECT_TRUE(it == proto_array_.begin() + 3); @@ -1292,8 +1292,8 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) { { string v = "f"; RepeatedPtrField<string>::pointer_iterator it = - lower_bound(proto_array_.pointer_begin(), proto_array_.pointer_end(), - &v, StringLessThan()); + std::lower_bound(proto_array_.pointer_begin(), + proto_array_.pointer_end(), &v, StringLessThan()); GOOGLE_CHECK(*it != NULL); @@ -1302,10 +1302,9 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) { } { string v = "f"; - RepeatedPtrField<string>::const_pointer_iterator it = - lower_bound(const_proto_array_->pointer_begin(), - const_proto_array_->pointer_end(), - &v, StringLessThan()); + RepeatedPtrField<string>::const_pointer_iterator it = std::lower_bound( + const_proto_array_->pointer_begin(), const_proto_array_->pointer_end(), + &v, StringLessThan()); GOOGLE_CHECK(*it != NULL); @@ -1343,9 +1342,8 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, Sort) { EXPECT_EQ("foo", proto_array_.Get(0)); EXPECT_EQ("n", proto_array_.Get(5)); EXPECT_EQ("x", proto_array_.Get(9)); - sort(proto_array_.pointer_begin(), - proto_array_.pointer_end(), - StringLessThan()); + std::sort(proto_array_.pointer_begin(), proto_array_.pointer_end(), + StringLessThan()); EXPECT_EQ("a", proto_array_.Get(0)); EXPECT_EQ("baz", proto_array_.Get(2)); EXPECT_EQ("y", proto_array_.Get(9)); @@ -1478,9 +1476,9 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, new_data->set_bb(i); } TestAllTypes testproto; - copy(data.begin(), data.end(), - AllocatedRepeatedPtrFieldBackInserter( - testproto.mutable_repeated_nested_message())); + std::copy(data.begin(), data.end(), + AllocatedRepeatedPtrFieldBackInserter( + testproto.mutable_repeated_nested_message())); EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString()); } @@ -1497,9 +1495,8 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, *new_data = "name-" + SimpleItoa(i); } TestAllTypes testproto; - copy(data.begin(), data.end(), - AllocatedRepeatedPtrFieldBackInserter( - testproto.mutable_repeated_string())); + std::copy(data.begin(), data.end(), AllocatedRepeatedPtrFieldBackInserter( + testproto.mutable_repeated_string())); EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString()); } diff --git a/src/google/protobuf/source_context.proto b/src/google/protobuf/source_context.proto new file mode 100644 index 00000000..2c8a17a8 --- /dev/null +++ b/src/google/protobuf/source_context.proto @@ -0,0 +1,46 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +syntax = "proto3"; + +package google.protobuf; + +option java_multiple_files = true; +option java_outer_classname = "SourceContextProto"; +option java_package = "com.google.protobuf"; +option objc_class_prefix = "GPB"; + + +// `SourceContext` represents information about the source of a +// protobuf element, like the file in which it is defined. +message SourceContext { + // The path-qualified name of the .proto file that contained the associated + // protobuf element. For example: `"google/protobuf/source.proto"`. + string file_name = 1; +} diff --git a/src/google/protobuf/struct.proto b/src/google/protobuf/struct.proto new file mode 100644 index 00000000..04d59f77 --- /dev/null +++ b/src/google/protobuf/struct.proto @@ -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. +syntax = "proto3"; + +package google.protobuf; + +option java_generate_equals_and_hash = true; +option java_multiple_files = true; +option java_outer_classname = "StructProto"; +option java_package = "com.google.protobuf"; +option objc_class_prefix = "GPB"; + + +// `Struct` represents a structured data value, consisting of fields +// which map to dynamically typed values. In some languages, `Struct` +// might be supported by a native representation. For example, in +// scripting languages like JS a struct is represented as an +// object. The details of that representation are described together +// with the proto support for the language. +message Struct { + // Map of dynamically typed values. + map<string, Value> fields = 1; +} + +// `Value` represents a dynamically typed value which can be either +// null, a number, a string, a boolean, a recursive struct value, or a +// list of values. A producer of value is expected to set one of that +// variants, absence of any variant indicates an error. +message Value { + oneof kind { + // Represents a null value. + NullValue null_value = 1; + + // Represents a double value. + double number_value = 2; + + // Represents a string value. + string string_value = 3; + + // Represents a boolean value. + bool bool_value = 4; + + // Represents a structured value. + Struct struct_value = 5; + + // Represents a repeated `Value`. + ListValue list_value = 6; + } +} + +// `ListValue` is a wrapper around a repeated field of values. +message ListValue { + // Repeated field of dynamically typed values. + repeated Value values = 1; +} + +// `NullValue` is a singleton enumeration to represent the null +// value for the `Value` type union. +enum NullValue { + // Null value. + NULL_VALUE = 0; +} diff --git a/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h b/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h index e3cd14cf..f5837c9e 100644 --- a/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h +++ b/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h @@ -65,7 +65,7 @@ inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, "2:\n" ".set pop\n" : "=&r" (prev), "=m" (*ptr), "=&r" (tmp) - : "Ir" (old_value), "r" (new_value), "m" (*ptr) + : "r" (old_value), "r" (new_value), "m" (*ptr) : "memory"); return prev; } @@ -197,7 +197,7 @@ inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, "2:\n" ".set pop\n" : "=&r" (prev), "=m" (*ptr), "=&r" (tmp) - : "Ir" (old_value), "r" (new_value), "m" (*ptr) + : "r" (old_value), "r" (new_value), "m" (*ptr) : "memory"); return prev; } diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h index b7e11749..c3f735a2 100644 --- a/src/google/protobuf/stubs/common.h +++ b/src/google/protobuf/stubs/common.h @@ -113,24 +113,24 @@ namespace internal { // The current version, represented as a single integer to make comparison // easier: major * 10^6 + minor * 10^3 + micro -#define GOOGLE_PROTOBUF_VERSION 2006002 +#define GOOGLE_PROTOBUF_VERSION 3000000 // The minimum library version which works with the current version of the // headers. -#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 2006000 +#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 3000000 // The minimum header version which works with the current version of // the library. This constant should only be used by protoc's C++ code // generator. -static const int kMinHeaderVersionForLibrary = 2006000; +static const int kMinHeaderVersionForLibrary = 3000000; // The minimum protoc version which works with the current version of the // headers. -#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 2006000 +#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 3000000 // The minimum header version which works with the current version of // protoc. This constant should only be used in VerifyVersion(). -static const int kMinHeaderVersionForProtoc = 2006000; +static const int kMinHeaderVersionForProtoc = 3000000; // Verifies that the headers and libraries are compatible. Use the macro // below to call this. @@ -314,6 +314,12 @@ inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64 v) { } #endif +#if defined(_MSC_VER) +#define GOOGLE_THREAD_LOCAL __declspec(thread) +#else +#define GOOGLE_THREAD_LOCAL __thread +#endif + // =================================================================== // from google3/base/basictypes.h @@ -381,8 +387,9 @@ struct CompileAssert { #undef GOOGLE_COMPILE_ASSERT #define GOOGLE_COMPILE_ASSERT(expr, msg) \ - typedef ::google::protobuf::internal::CompileAssert<(bool(expr))> \ - msg[bool(expr) ? 1 : -1] + ::google::protobuf::internal::CompileAssert<(bool(expr))> \ + msg[bool(expr) ? 1 : -1]; \ + (void)msg // Implementation details of COMPILE_ASSERT: diff --git a/src/google/protobuf/stubs/common_unittest.cc b/src/google/protobuf/stubs/common_unittest.cc index 7eb4e317..5f458e98 100644 --- a/src/google/protobuf/stubs/common_unittest.cc +++ b/src/google/protobuf/stubs/common_unittest.cc @@ -95,9 +95,9 @@ TEST(LoggingTest, DefaultLogging) { string text = GetCapturedTestStderr(); EXPECT_EQ( - "[libprotobuf INFO "__FILE__":" + SimpleItoa(line + 1) + "] A message.\n" - "[libprotobuf WARNING "__FILE__":" + SimpleItoa(line + 2) + "] A warning.\n" - "[libprotobuf ERROR "__FILE__":" + SimpleItoa(line + 3) + "] An error.\n", + "[libprotobuf INFO " __FILE__ ":" + SimpleItoa(line + 1) + "] A message.\n" + "[libprotobuf WARNING " __FILE__ ":" + SimpleItoa(line + 2) + "] A warning.\n" + "[libprotobuf ERROR " __FILE__ ":" + SimpleItoa(line + 3) + "] An error.\n", text); } @@ -128,10 +128,10 @@ TEST(LoggingTest, CaptureLogging) { ASSERT_EQ(2, captured_messages_.size()); EXPECT_EQ( - "2 "__FILE__":" + SimpleItoa(start_line + 1) + ": An error.", + "2 " __FILE__ ":" + SimpleItoa(start_line + 1) + ": An error.", captured_messages_[0]); EXPECT_EQ( - "1 "__FILE__":" + SimpleItoa(start_line + 2) + ": A warning.", + "1 " __FILE__ ":" + SimpleItoa(start_line + 2) + ": A warning.", captured_messages_[1]); } @@ -154,10 +154,10 @@ TEST(LoggingTest, SilenceLogging) { ASSERT_EQ(2, captured_messages_.size()); EXPECT_EQ( - "0 "__FILE__":" + SimpleItoa(line1) + ": Visible1", + "0 " __FILE__ ":" + SimpleItoa(line1) + ": Visible1", captured_messages_[0]); EXPECT_EQ( - "0 "__FILE__":" + SimpleItoa(line2) + ": Visible2", + "0 " __FILE__ ":" + SimpleItoa(line2) + ": Visible2", captured_messages_[1]); } diff --git a/src/google/protobuf/stubs/fastmem.h b/src/google/protobuf/stubs/fastmem.h index e553f142..763a6e60 100644 --- a/src/google/protobuf/stubs/fastmem.h +++ b/src/google/protobuf/stubs/fastmem.h @@ -46,7 +46,6 @@ #define GOOGLE_PROTOBUF_STUBS_FASTMEM_H_ #include <stddef.h> -#include <stdint.h> #include <stdio.h> #include <string.h> diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h index 5b6a073d..82d5052e 100644..100755 --- a/src/google/protobuf/stubs/hash.h +++ b/src/google/protobuf/stubs/hash.h @@ -37,13 +37,14 @@ #include <string.h> #include <google/protobuf/stubs/common.h> -#include "config.h" +#include <google/protobuf/stubs/pbconfig.h> -#if defined(HAVE_HASH_MAP) && defined(HAVE_HASH_SET) -#include HASH_MAP_H -#include HASH_SET_H +#if defined(GOOGLE_PROTOBUF_HAVE_HASH_MAP) && \ + defined(GOOGLE_PROTOBUF_HAVE_HASH_SET) +#include GOOGLE_PROTOBUF_HASH_MAP_H +#include GOOGLE_PROTOBUF_HASH_SET_H #else -#define MISSING_HASH +#define GOOGLE_PROTOBUF_MISSING_HASH #include <map> #include <set> #endif @@ -51,7 +52,7 @@ namespace google { namespace protobuf { -#ifdef MISSING_HASH +#ifdef GOOGLE_PROTOBUF_MISSING_HASH // This system doesn't have hash_map or hash_set. Emulate them using map and // set. @@ -88,15 +89,17 @@ struct hash<const char*> { template <typename Key, typename Data, typename HashFcn = hash<Key>, - typename EqualKey = int > -class hash_map : public std::map<Key, Data, HashFcn> { + typename EqualKey = std::equal_to<Key>, + typename Alloc = std::allocator< std::pair<const Key, Data> > > +class hash_map : public std::map<Key, Data, HashFcn, EqualKey, Alloc> { public: - hash_map(int = 0) {} + hash_map(int = 0, const HashFcn& = HashFcn(), const EqualKey& = EqualKey(), + const Alloc& = Alloc()) {} }; template <typename Key, typename HashFcn = hash<Key>, - typename EqualKey = int > + typename EqualKey = std::equal_to<Key> > class hash_set : public std::set<Key, HashFcn> { public: hash_set(int = 0) {} @@ -105,7 +108,7 @@ class hash_set : public std::set<Key, HashFcn> { #elif defined(_MSC_VER) && !defined(_STLPORT_VERSION) template <typename Key> -struct hash : public HASH_NAMESPACE::hash_compare<Key> { +struct hash : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash_compare<Key> { }; // MSVC's hash_compare<const char*> hashes based on the string contents but @@ -119,23 +122,26 @@ class CstringLess { template <> struct hash<const char*> - : public HASH_NAMESPACE::hash_compare<const char*, CstringLess> { -}; + : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash_compare< + const char*, CstringLess> {}; template <typename Key, typename Data, typename HashFcn = hash<Key>, - typename EqualKey = int > -class hash_map : public HASH_NAMESPACE::hash_map< - Key, Data, HashFcn> { + typename EqualKey = std::equal_to<Key>, + typename Alloc = std::allocator< std::pair<const Key, Data> > > +class hash_map + : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< + Key, Data, HashFcn, EqualKey, Alloc> { public: - hash_map(int = 0) {} + hash_map(int = 0, const HashFcn& = HashFcn(), const EqualKey& = EqualKey(), + const Alloc& = Alloc()) {} }; -template <typename Key, - typename HashFcn = hash<Key>, - typename EqualKey = int > -class hash_set : public HASH_NAMESPACE::hash_set< - Key, HashFcn> { +template <typename Key, typename HashFcn = hash<Key>, + typename EqualKey = std::equal_to<Key> > +class hash_set + : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS< + Key, HashFcn, EqualKey> { public: hash_set(int = 0) {} }; @@ -143,7 +149,7 @@ class hash_set : public HASH_NAMESPACE::hash_set< #else template <typename Key> -struct hash : public HASH_NAMESPACE::hash<Key> { +struct hash : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash<Key> { }; template <typename Key> @@ -168,23 +174,27 @@ struct hash<const char*> { template <typename Key, typename Data, typename HashFcn = hash<Key>, - typename EqualKey = std::equal_to<Key> > -class hash_map : public HASH_NAMESPACE::HASH_MAP_CLASS< - Key, Data, HashFcn, EqualKey> { + typename EqualKey = std::equal_to<Key>, + typename Alloc = std::allocator< std::pair<const Key, Data> > > +class hash_map + : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< + Key, Data, HashFcn, EqualKey, Alloc> { public: - hash_map(int = 0) {} + hash_map(int = 0, const HashFcn& = HashFcn(), const EqualKey& = EqualKey(), + const Alloc& = Alloc()) {} }; -template <typename Key, - typename HashFcn = hash<Key>, +template <typename Key, typename HashFcn = hash<Key>, typename EqualKey = std::equal_to<Key> > -class hash_set : public HASH_NAMESPACE::HASH_SET_CLASS< - Key, HashFcn, EqualKey> { +class hash_set + : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS< + Key, HashFcn, EqualKey> { public: hash_set(int = 0) {} }; -#endif +#undef GOOGLE_PROTOBUF_MISSING_HASH +#endif // !GOOGLE_PROTOBUF_MISSING_HASH template <> struct hash<string> { diff --git a/src/google/protobuf/stubs/map_util.h b/src/google/protobuf/stubs/map_util.h index 7495cb6a..4cccbbed 100644 --- a/src/google/protobuf/stubs/map_util.h +++ b/src/google/protobuf/stubs/map_util.h @@ -353,7 +353,6 @@ template <class Collection> void InsertOrDie(Collection* const collection, const typename Collection::value_type::first_type& key, const typename Collection::value_type::second_type& data) { - typedef typename Collection::value_type value_type; GOOGLE_CHECK(InsertIfNotPresent(collection, key, data)) << "duplicate key: " << key; } @@ -364,7 +363,6 @@ void InsertOrDieNoPrint( Collection* const collection, const typename Collection::value_type::first_type& key, const typename Collection::value_type::second_type& data) { - typedef typename Collection::value_type value_type; GOOGLE_CHECK(InsertIfNotPresent(collection, key, data)) << "duplicate key."; } diff --git a/src/google/protobuf/stubs/singleton.h b/src/google/protobuf/stubs/singleton.h index e123e4fe..9301f549 100644 --- a/src/google/protobuf/stubs/singleton.h +++ b/src/google/protobuf/stubs/singleton.h @@ -44,6 +44,10 @@ class Singleton { GoogleOnceInit(&once_, &Singleton<T>::Init); return instance_; } + static void ShutDown() { + delete instance_; + instance_ = NULL; + } private: static void Init() { instance_ = new T(); @@ -56,7 +60,7 @@ template<typename T> ProtobufOnceType Singleton<T>::once_; template<typename T> -T* Singleton<T>::instance_; +T* Singleton<T>::instance_ = NULL; } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc index 86d45685..7955d261 100644 --- a/src/google/protobuf/stubs/strutil.cc +++ b/src/google/protobuf/stubs/strutil.cc @@ -1303,6 +1303,211 @@ string ToHex(uint64 num) { return string(bufptr, buf + 16 - bufptr); } +namespace strings { + +AlphaNum::AlphaNum(strings::Hex hex) { + char *const end = &digits[kFastToBufferSize]; + char *writer = end; + uint64 value = hex.value; + uint64 width = hex.spec; + // We accomplish minimum width by OR'ing in 0x10000 to the user's value, + // where 0x10000 is the smallest hex number that is as wide as the user + // asked for. + uint64 mask = ((static_cast<uint64>(1) << (width - 1) * 4)) | value; + static const char hexdigits[] = "0123456789abcdef"; + do { + *--writer = hexdigits[value & 0xF]; + value >>= 4; + mask >>= 4; + } while (mask != 0); + piece_data_ = writer; + piece_size_ = end - writer; +} + +} // namespace strings + +// ---------------------------------------------------------------------- +// StrCat() +// This merges the given strings or integers, with no delimiter. This +// is designed to be the fastest possible way to construct a string out +// of a mix of raw C strings, C++ strings, and integer values. +// ---------------------------------------------------------------------- + +// Append is merely a version of memcpy that returns the address of the byte +// after the area just overwritten. It comes in multiple flavors to minimize +// call overhead. +static char *Append1(char *out, const AlphaNum &x) { + memcpy(out, x.data(), x.size()); + return out + x.size(); +} + +static char *Append2(char *out, const AlphaNum &x1, const AlphaNum &x2) { + memcpy(out, x1.data(), x1.size()); + out += x1.size(); + + memcpy(out, x2.data(), x2.size()); + return out + x2.size(); +} + +static char *Append4(char *out, + const AlphaNum &x1, const AlphaNum &x2, + const AlphaNum &x3, const AlphaNum &x4) { + memcpy(out, x1.data(), x1.size()); + out += x1.size(); + + memcpy(out, x2.data(), x2.size()); + out += x2.size(); + + memcpy(out, x3.data(), x3.size()); + out += x3.size(); + + memcpy(out, x4.data(), x4.size()); + return out + x4.size(); +} + +string StrCat(const AlphaNum &a, const AlphaNum &b) { + string result; + result.resize(a.size() + b.size()); + char *const begin = &*result.begin(); + char *out = Append2(begin, a, b); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) { + string result; + result.resize(a.size() + b.size() + c.size()); + char *const begin = &*result.begin(); + char *out = Append2(begin, a, b); + out = Append1(out, c); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d) { + string result; + result.resize(a.size() + b.size() + c.size() + d.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e) { + string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append1(out, e); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f) { + string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + + f.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append2(out, e, f); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g) { + string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + + f.size() + g.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append2(out, e, f); + out = Append1(out, g); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g, const AlphaNum &h) { + string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + + f.size() + g.size() + h.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append4(out, e, f, g, h); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g, const AlphaNum &h, const AlphaNum &i) { + string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + + f.size() + g.size() + h.size() + i.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append4(out, e, f, g, h); + out = Append1(out, i); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +// It's possible to call StrAppend with a char * pointer that is partway into +// the string we're appending to. However the results of this are random. +// Therefore, check for this in debug mode. Use unsigned math so we only have +// to do one comparison. +#define GOOGLE_DCHECK_NO_OVERLAP(dest, src) \ + GOOGLE_DCHECK_GT(uintptr_t((src).data() - (dest).data()), \ + uintptr_t((dest).size())) + +void StrAppend(string *result, const AlphaNum &a) { + GOOGLE_DCHECK_NO_OVERLAP(*result, a); + result->append(a.data(), a.size()); +} + +void StrAppend(string *result, const AlphaNum &a, const AlphaNum &b) { + GOOGLE_DCHECK_NO_OVERLAP(*result, a); + GOOGLE_DCHECK_NO_OVERLAP(*result, b); + string::size_type old_size = result->size(); + result->resize(old_size + a.size() + b.size()); + char *const begin = &*result->begin(); + char *out = Append2(begin + old_size, a, b); + GOOGLE_DCHECK_EQ(out, begin + result->size()); +} + +void StrAppend(string *result, + const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) { + GOOGLE_DCHECK_NO_OVERLAP(*result, a); + GOOGLE_DCHECK_NO_OVERLAP(*result, b); + GOOGLE_DCHECK_NO_OVERLAP(*result, c); + string::size_type old_size = result->size(); + result->resize(old_size + a.size() + b.size() + c.size()); + char *const begin = &*result->begin(); + char *out = Append2(begin + old_size, a, b); + out = Append1(out, c); + GOOGLE_DCHECK_EQ(out, begin + result->size()); +} + +void StrAppend(string *result, + const AlphaNum &a, const AlphaNum &b, + const AlphaNum &c, const AlphaNum &d) { + GOOGLE_DCHECK_NO_OVERLAP(*result, a); + GOOGLE_DCHECK_NO_OVERLAP(*result, b); + GOOGLE_DCHECK_NO_OVERLAP(*result, c); + GOOGLE_DCHECK_NO_OVERLAP(*result, d); + string::size_type old_size = result->size(); + result->resize(old_size + a.size() + b.size() + c.size() + d.size()); + char *const begin = &*result->begin(); + char *out = Append4(begin + old_size, a, b, c, d); + GOOGLE_DCHECK_EQ(out, begin + result->size()); +} + int GlobalReplaceSubstring(const string& substring, const string& replacement, string* s) { diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h index f2e1a944..920701eb 100644 --- a/src/google/protobuf/stubs/strutil.h +++ b/src/google/protobuf/stubs/strutil.h @@ -495,57 +495,168 @@ LIBPROTOBUF_EXPORT char* FloatToBuffer(float i, char* buffer); static const int kDoubleToBufferSize = 32; static const int kFloatToBufferSize = 24; -// ---------------------------------------------------------------------- -// ToString() are internal help methods used in StrCat() and Join() -// ---------------------------------------------------------------------- -namespace internal { -inline string ToString(int i) { - return SimpleItoa(i); -} +namespace strings { -inline string ToString(string a) { - return a; -} -} // namespace internal +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; + template <class Int> + explicit Hex(Int v, PadSpec s = NONE) + : spec(s) { + // Prevent sign-extension by casting integers to + // their unsigned counterparts. +#ifdef LANG_CXX11 + static_assert( + sizeof(v) == 1 || sizeof(v) == 2 || sizeof(v) == 4 || sizeof(v) == 8, + "Unknown integer type"); +#endif + value = sizeof(v) == 1 ? static_cast<uint8>(v) + : sizeof(v) == 2 ? static_cast<uint16>(v) + : sizeof(v) == 4 ? static_cast<uint32>(v) + : static_cast<uint64>(v); + } +}; -// ---------------------------------------------------------------------- -// StrCat() -// These methods join some strings together. -// ---------------------------------------------------------------------- -template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6, typename T7> -string StrCat( - const T1& a, const T2& b, const T3& c, const T4& d, const T5& e, - const T6& f, const T7& g) { - return internal::ToString(a) + internal::ToString(b) + - internal::ToString(c) + internal::ToString(d) + internal::ToString(e) + - internal::ToString(f) + internal::ToString(g); -} +struct AlphaNum { + const char *piece_data_; // move these to string_ref eventually + size_t piece_size_; // move these to string_ref eventually -template <typename T1, typename T2, typename T3, typename T4, typename T5> -string StrCat( - const T1& a, const T2& b, const T3& c, const T4& d, const T5& e) { - return internal::ToString(a) + internal::ToString(b) + - internal::ToString(c) + internal::ToString(d) + internal::ToString(e); -} + char digits[kFastToBufferSize]; -template <typename T1, typename T2, typename T3, typename T4> -string StrCat( - const T1& a, const T2& b, const T3& c, const T4& d) { - return internal::ToString(a) + internal::ToString(b) + - internal::ToString(c) + internal::ToString(d); -} + // No bool ctor -- bools convert to an integral type. + // A bool ctor would also convert incoming pointers (bletch). -template <typename T1, typename T2, typename T3> -string StrCat(const T1& a, const T2& b, const T3& c) { - return internal::ToString(a) + internal::ToString(b) + - internal::ToString(c); -} + AlphaNum(int32 i32) + : piece_data_(digits), + piece_size_(FastInt32ToBufferLeft(i32, digits) - &digits[0]) {} + AlphaNum(uint32 u32) + : piece_data_(digits), + piece_size_(FastUInt32ToBufferLeft(u32, digits) - &digits[0]) {} + AlphaNum(int64 i64) + : piece_data_(digits), + piece_size_(FastInt64ToBufferLeft(i64, digits) - &digits[0]) {} + AlphaNum(uint64 u64) + : piece_data_(digits), + piece_size_(FastUInt64ToBufferLeft(u64, digits) - &digits[0]) {} -template <typename T1, typename T2> -string StrCat(const T1& a, const T2& b) { - return internal::ToString(a) + internal::ToString(b); -} + AlphaNum(float f) + : piece_data_(digits), piece_size_(strlen(FloatToBuffer(f, digits))) {} + AlphaNum(double f) + : piece_data_(digits), piece_size_(strlen(DoubleToBuffer(f, digits))) {} + + AlphaNum(Hex hex); + + AlphaNum(const char* c_str) + : piece_data_(c_str), piece_size_(strlen(c_str)) {} + // TODO: Add a string_ref constructor, eventually + // AlphaNum(const StringPiece &pc) : piece(pc) {} + + AlphaNum(const string& str) + : piece_data_(str.data()), piece_size_(str.size()) {} + + size_t size() const { return piece_size_; } + const char *data() const { return piece_data_; } + + private: + // Use ":" not ':' + AlphaNum(char c); // NOLINT(runtime/explicit) + + // Disallow copy and assign. + AlphaNum(const AlphaNum&); + void operator=(const AlphaNum&); +}; + +} // namespace strings + +using strings::AlphaNum; + +// ---------------------------------------------------------------------- +// StrCat() +// This merges the given strings or numbers, with no delimiter. This +// is designed to be the fastest possible way to construct a string out +// of a mix of raw C strings, strings, bool values, +// and numeric values. +// +// Don't use this for user-visible strings. The localization process +// works poorly on strings built up out of fragments. +// +// For clarity and performance, don't use StrCat when appending to a +// string. In particular, avoid using any of these (anti-)patterns: +// str.append(StrCat(...) +// str += StrCat(...) +// str = StrCat(str, ...) +// where the last is the worse, with the potential to change a loop +// from a linear time operation with O(1) dynamic allocations into a +// quadratic time operation with O(n) dynamic allocations. StrAppend +// is a better choice than any of the above, subject to the restriction +// of StrAppend(&str, a, b, c, ...) that none of the a, b, c, ... may +// be a reference into str. +// ---------------------------------------------------------------------- + +string StrCat(const AlphaNum &a, const AlphaNum &b); +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c); +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d); +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e); +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f); +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g); +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g, const AlphaNum &h); +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g, const AlphaNum &h, const AlphaNum &i); + +inline string StrCat(const AlphaNum& a) { return string(a.data(), a.size()); } + +// ---------------------------------------------------------------------- +// StrAppend() +// Same as above, but adds the output to the given string. +// WARNING: For speed, StrAppend does not try to check each of its input +// arguments to be sure that they are not a subset of the string being +// appended to. That is, while this will work: +// +// string s = "foo"; +// s += s; +// +// This will not (necessarily) work: +// +// string s = "foo"; +// StrAppend(&s, s); +// +// Note: while StrCat supports appending up to 9 arguments, StrAppend +// is currently limited to 4. That's rarely an issue except when +// automatically transforming StrCat to StrAppend, and can easily be +// worked around as consecutive calls to StrAppend are quite efficient. +// ---------------------------------------------------------------------- + +void StrAppend(string* dest, const AlphaNum& a); +void StrAppend(string* dest, const AlphaNum& a, const AlphaNum& b); +void StrAppend(string* dest, const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c); +void StrAppend(string* dest, const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d); // ---------------------------------------------------------------------- // Join() @@ -559,7 +670,7 @@ void Join(Iterator start, Iterator end, if (it != start) { result->append(delim); } - result->append(internal::ToString(*it)); + StrAppend(result, *it); } } diff --git a/src/google/protobuf/stubs/type_traits.h b/src/google/protobuf/stubs/type_traits.h index f5365c38..b58cae3f 100644 --- a/src/google/protobuf/stubs/type_traits.h +++ b/src/google/protobuf/stubs/type_traits.h @@ -103,7 +103,7 @@ template <class T> struct remove_reference; template <class T> struct add_reference; template <class T> struct remove_pointer; template <class T, class U> struct is_same; -#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) +#if !(defined(__GNUC__) && __GNUC__ <= 3) template <class From, class To> struct is_convertible; #endif @@ -322,7 +322,7 @@ template<typename T, typename U> struct is_same : public false_type { }; template<typename T> struct is_same<T, T> : public true_type { }; // Specified by TR1 [4.6] Relationships between types -#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) +#if !(defined(__GNUC__) && __GNUC__ <= 3) namespace type_traits_internal { // This class is an implementation detail for is_convertible, and you @@ -339,6 +339,9 @@ struct ConvertHelper { static small_ Test(To); static big_ Test(...); static From Create(); + enum { + value = sizeof(Test(Create())) == sizeof(small_) + }; }; } // namespace type_traits_internal @@ -346,9 +349,7 @@ struct ConvertHelper { template <typename From, typename To> struct is_convertible : integral_constant<bool, - sizeof(type_traits_internal::ConvertHelper<From, To>::Test( - type_traits_internal::ConvertHelper<From, To>::Create())) - == sizeof(small_)> { + type_traits_internal::ConvertHelper<From, To>::value> { }; #endif diff --git a/src/google/protobuf/stubs/type_traits_unittest.cc b/src/google/protobuf/stubs/type_traits_unittest.cc index b42b9e83..49c10ace 100644 --- a/src/google/protobuf/stubs/type_traits_unittest.cc +++ b/src/google/protobuf/stubs/type_traits_unittest.cc @@ -610,7 +610,7 @@ TEST(TypeTraitsTest, TestIsSame) { } TEST(TypeTraitsTest, TestConvertible) { -#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) +#if !(defined(__GNUC__) && __GNUC__ <= 3) EXPECT_TRUE((is_convertible<int, int>::value)); EXPECT_TRUE((is_convertible<int, long>::value)); EXPECT_TRUE((is_convertible<long, int>::value)); diff --git a/src/google/protobuf/testdata/golden_message_proto3 b/src/google/protobuf/testdata/golden_message_proto3 Binary files differnew file mode 100644 index 00000000..934f36fa --- /dev/null +++ b/src/google/protobuf/testdata/golden_message_proto3 diff --git a/src/google/protobuf/testing/file.cc b/src/google/protobuf/testing/file.cc index 5344ec15..3d07b127 100644 --- a/src/google/protobuf/testing/file.cc +++ b/src/google/protobuf/testing/file.cc @@ -192,5 +192,9 @@ void File::DeleteRecursively(const string& name, #endif } +bool File::ChangeWorkingDirectory(const string& new_working_directory) { + return chdir(new_working_directory.c_str()) == 0; +} + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/testing/file.h b/src/google/protobuf/testing/file.h index d2aeabf2..2f63f80e 100644 --- a/src/google/protobuf/testing/file.h +++ b/src/google/protobuf/testing/file.h @@ -77,6 +77,9 @@ class File { static void DeleteRecursively(const string& name, void* dummy1, void* dummy2); + // Change working directory to given directory. + static bool ChangeWorkingDirectory(const string& new_working_directory); + static bool GetContents( const string& name, string* output, bool /*is_default*/) { return ReadFileToString(name, output); diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index 8e867c09..ec070c51 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -1360,9 +1360,8 @@ void TextFormat::Printer::SetDefaultFieldValuePrinter( bool TextFormat::Printer::RegisterFieldValuePrinter( const FieldDescriptor* field, const FieldValuePrinter* printer) { - return field != NULL - && printer != NULL - && custom_printers_.insert(make_pair(field, printer)).second; + return field != NULL && printer != NULL && + custom_printers_.insert(std::make_pair(field, printer)).second; } bool TextFormat::Printer::PrintToString(const Message& message, @@ -1422,7 +1421,7 @@ void TextFormat::Printer::Print(const Message& message, vector<const FieldDescriptor*> fields; reflection->ListFields(message, &fields); if (print_message_fields_in_index_order_) { - sort(fields.begin(), fields.end(), FieldIndexSorter()); + std::sort(fields.begin(), fields.end(), FieldIndexSorter()); } for (int i = 0; i < fields.size(); i++) { PrintField(message, reflection, fields[i], generator); diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h index 44d68cab..9e2cb070 100644 --- a/src/google/protobuf/text_format.h +++ b/src/google/protobuf/text_format.h @@ -278,8 +278,20 @@ class LIBPROTOBUF_EXPORT TextFormat { }; // Parses a text-format protocol message from the given input stream to - // the given message object. This function parses the format written - // by Print(). + // the given message object. This function parses the human-readable format + // written by Print(). Returns true on success. The message is cleared first, + // even if the function fails -- See Merge() to avoid this behavior. + // + // Example input: "user {\n id: 123 extra { gender: MALE language: 'en' }\n}" + // + // One use for this function is parsing handwritten strings in test code. + // Another use is to parse the output from google::protobuf::Message::DebugString() + // (or ShortDebugString()), because these functions output using + // google::protobuf::TextFormat::Print(). + // + // If you would like to read a protocol buffer serialized in the + // (non-human-readable) binary wire format, see + // google::protobuf::MessageLite::ParseFromString(). static bool Parse(io::ZeroCopyInputStream* input, Message* output); // Like Parse(), but reads directly from a string. static bool ParseFromString(const string& input, Message* output); diff --git a/src/google/protobuf/timestamp.proto b/src/google/protobuf/timestamp.proto new file mode 100644 index 00000000..72e8914c --- /dev/null +++ b/src/google/protobuf/timestamp.proto @@ -0,0 +1,105 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +syntax = "proto3"; + +package google.protobuf; + +option java_generate_equals_and_hash = true; +option java_multiple_files = true; +option java_outer_classname = "TimestampProto"; +option java_package = "com.google.protobuf"; +option objc_class_prefix = "GPB"; + + +// A Timestamp represents a point in time independent of any time zone +// or calendar, represented as seconds and fractions of seconds at +// nanosecond resolution in UTC Epoch time. It is encoded using the +// Proleptic Gregorian Calendar which extends the Gregorian calendar +// backwards to year one. It is encoded assuming all minutes are 60 +// seconds long, i.e. leap seconds are "smeared" so that no leap second +// table is needed for interpretation. Range is from +// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. +// By restricting to that range, we ensure that we can convert to +// and from RFC 3339 date strings. +// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt). +// +// Example 1: Compute Timestamp from POSIX `time()`. +// +// Timestamp timestamp; +// timestamp.set_seconds(time(NULL)); +// timestamp.set_nanos(0); +// +// Example 2: Compute Timestamp from POSIX `gettimeofday()`. +// +// struct timeval tv; +// gettimeofday(&tv, NULL); +// +// Timestamp timestamp; +// timestamp.set_seconds(tv.tv_sec); +// timestamp.set_nanos(tv.tv_usec * 1000); +// +// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. +// +// FILETIME ft; +// GetSystemTimeAsFileTime(&ft); +// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; +// +// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z +// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. +// Timestamp timestamp; +// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); +// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); +// +// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. +// +// long millis = System.currentTimeMillis(); +// +// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) +// .setNanos((int) ((millis % 1000) * 1000000)).build(); +// +// Example 5: Compute Timestamp from Python `datetime.datetime`. +// +// now = datetime.datetime.utcnow() +// seconds = int(time.mktime(now.timetuple())) +// nanos = now.microsecond * 1000 +// timestamp = Timestamp(seconds=seconds, nanos=nanos) +// +message Timestamp { + // Represents seconds of UTC time since Unix epoch + // 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to + // 9999-12-31T23:59:59Z inclusive. + int64 seconds = 1; + + // Non-negative fractions of a second at nanosecond resolution. Negative + // second values with fractions must still have non-negative nanos values + // that count forward in time. Must be from 0 to 999,999,999 + // inclusive. + int32 nanos = 2; +} diff --git a/src/google/protobuf/type.proto b/src/google/protobuf/type.proto new file mode 100644 index 00000000..ace5d995 --- /dev/null +++ b/src/google/protobuf/type.proto @@ -0,0 +1,197 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +syntax = "proto3"; + +package google.protobuf; + +import "google/protobuf/any.proto"; +import "google/protobuf/source_context.proto"; + +option java_multiple_files = true; +option java_outer_classname = "TypeProto"; +option java_package = "com.google.protobuf"; +option objc_class_prefix = "GPB"; + + +// A light-weight descriptor for a proto message type. +message Type { + // The fully qualified message name. + string name = 1; + + // The list of fields. + repeated Field fields = 2; + + // The list of oneof definitions. + // The list of oneofs declared in this Type + repeated string oneofs = 3; + + // The proto options. + repeated Option options = 4; + + // The source context. + SourceContext source_context = 5; +} + +// Field represents a single field of a message type. +message Field { + // Kind represents a basic field type. + enum Kind { + // Field type unknown. + TYPE_UNKNOWN = 0; + + // Field type double. + TYPE_DOUBLE = 1; + + // Field type float. + TYPE_FLOAT = 2; + + // Field type int64. + TYPE_INT64 = 3; + + // Field type uint64. + TYPE_UINT64 = 4; + + // Field type int32. + TYPE_INT32 = 5; + + // Field type fixed64. + TYPE_FIXED64 = 6; + + // Field type fixed32. + TYPE_FIXED32 = 7; + + // Field type bool. + TYPE_BOOL = 8; + + // Field type string. + TYPE_STRING = 9; + + // Field type message. + TYPE_MESSAGE = 11; + + // Field type bytes. + TYPE_BYTES = 12; + + // Field type uint32. + TYPE_UINT32 = 13; + + // Field type enum. + TYPE_ENUM = 14; + + // Field type sfixed32. + TYPE_SFIXED32 = 15; + + // Field type sfixed64. + TYPE_SFIXED64 = 16; + + // Field type sint32. + TYPE_SINT32 = 17; + + // Field type sint64. + TYPE_SINT64 = 18; + } + + // Cardinality represents whether a field is optional, required, or + // repeated. + enum Cardinality { + // The field cardinality is unknown. Typically an error condition. + CARDINALITY_UNKNOWN = 0; + + // For optional fields. + CARDINALITY_OPTIONAL = 1; + + // For required fields. Not used for proto3. + CARDINALITY_REQUIRED = 2; + + // For repeated fields. + CARDINALITY_REPEATED = 3; + } + + // The field kind. + Kind kind = 1; + + // The field cardinality, i.e. optional/required/repeated. + Cardinality cardinality = 2; + + // The proto field number. + int32 number = 3; + + // The field name. + string name = 4; + + // The type URL (without the scheme) when the type is MESSAGE or ENUM, + // such as `type.googleapis.com/google.protobuf.Empty`. + string type_url = 6; + + // Index in Type.oneofs. Starts at 1. Zero means no oneof mapping. + int32 oneof_index = 7; + + // Whether to use alternative packed wire representation. + bool packed = 8; + + // The proto options. + repeated Option options = 9; +} + +// Enum type definition. +message Enum { + // Enum type name. + string name = 1; + + // Enum value definitions. + repeated EnumValue enumvalue = 2; + + // Proto options for the enum type. + repeated Option options = 3; + + // The source context. + SourceContext source_context = 4; +} + +// Enum value definition. +message EnumValue { + // Enum value name. + string name = 1; + + // Enum value number. + int32 number = 2; + + // Proto options for the enum value. + repeated Option options = 3; +} + +// Proto option attached to messages/fields/enums etc. +message Option { + // Proto option name. + string name = 1; + + // Proto option value. + Any value = 2; +} diff --git a/src/google/protobuf/unittest_drop_unknown_fields.proto b/src/google/protobuf/unittest_drop_unknown_fields.proto index 66b31acf..2e513eb3 100644 --- a/src/google/protobuf/unittest_drop_unknown_fields.proto +++ b/src/google/protobuf/unittest_drop_unknown_fields.proto @@ -31,6 +31,7 @@ syntax = "proto3"; package unittest_drop_unknown_fields; +option objc_class_prefix = "DropUnknowns"; message Foo { enum NestedEnum { diff --git a/src/google/protobuf/unittest_no_arena.proto b/src/google/protobuf/unittest_no_arena.proto index 1a420838..36fb8656 100644 --- a/src/google/protobuf/unittest_no_arena.proto +++ b/src/google/protobuf/unittest_no_arena.proto @@ -113,7 +113,7 @@ message TestAllTypes { optional protobuf_unittest_import.PublicImportMessage optional_public_import_message = 26; - optional NestedMessage optional_lazy_message = 27 [lazy=true]; + optional NestedMessage optional_message = 27 [lazy=true]; // Repeated repeated int32 repeated_int32 = 31; @@ -180,6 +180,7 @@ message TestAllTypes { NestedMessage oneof_nested_message = 112; string oneof_string = 113; bytes oneof_bytes = 114; + NestedMessage lazy_oneof_nested_message = 115 [lazy=true]; } } diff --git a/src/google/protobuf/unittest_preserve_unknown_enum.proto b/src/google/protobuf/unittest_preserve_unknown_enum.proto index ba050d70..e7929699 100644 --- a/src/google/protobuf/unittest_preserve_unknown_enum.proto +++ b/src/google/protobuf/unittest_preserve_unknown_enum.proto @@ -30,7 +30,8 @@ syntax = "proto3"; -package proto2_preserve_unknown_enum_unittest; +package proto3_preserve_unknown_enum_unittest; +option objc_class_prefix = "UnknownEnums"; enum MyEnum { FOO = 0; @@ -49,9 +50,10 @@ message MyMessage { optional MyEnum e = 1; repeated MyEnum repeated_e = 2; repeated MyEnum repeated_packed_e = 3 [packed=true]; + repeated MyEnumPlusExtra repeated_packed_unexpected_e = 4; // not packed oneof o { - MyEnum oneof_e_1 = 4; - MyEnum oneof_e_2 = 5; + MyEnum oneof_e_1 = 5; + MyEnum oneof_e_2 = 6; } } @@ -59,8 +61,9 @@ message MyMessagePlusExtra { optional MyEnumPlusExtra e = 1; repeated MyEnumPlusExtra repeated_e = 2; repeated MyEnumPlusExtra repeated_packed_e = 3 [packed=true]; + repeated MyEnumPlusExtra repeated_packed_unexpected_e = 4 [packed=true]; oneof o { - MyEnumPlusExtra oneof_e_1 = 4; - MyEnumPlusExtra oneof_e_2 = 5; + MyEnumPlusExtra oneof_e_1 = 5; + MyEnumPlusExtra oneof_e_2 = 6; } } diff --git a/src/google/protobuf/unittest_preserve_unknown_enum2.proto b/src/google/protobuf/unittest_preserve_unknown_enum2.proto new file mode 100644 index 00000000..adf42968 --- /dev/null +++ b/src/google/protobuf/unittest_preserve_unknown_enum2.proto @@ -0,0 +1,50 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package proto2_preserve_unknown_enum_unittest; + +enum MyEnum { + FOO = 0; + BAR = 1; + BAZ = 2; +} + +message MyMessage { + optional MyEnum e = 1; + repeated MyEnum repeated_e = 2; + repeated MyEnum repeated_packed_e = 3 [packed=true]; + repeated MyEnum repeated_packed_unexpected_e = 4; // not packed + oneof o { + MyEnum oneof_e_1 = 5; + MyEnum oneof_e_2 = 6; + } +} diff --git a/src/google/protobuf/unittest_proto3_arena.proto b/src/google/protobuf/unittest_proto3_arena.proto index 53f23d87..6d7bada8 100644 --- a/src/google/protobuf/unittest_proto3_arena.proto +++ b/src/google/protobuf/unittest_proto3_arena.proto @@ -47,9 +47,10 @@ message TestAllTypes { } enum NestedEnum { - FOO = 0; - BAR = 1; - BAZ = 2; + ZERO = 0; + FOO = 1; + BAR = 2; + BAZ = 3; NEG = -1; // Intentionally negative. } @@ -81,6 +82,11 @@ message TestAllTypes { optional NestedEnum optional_nested_enum = 21; optional ForeignEnum optional_foreign_enum = 22; + // Omitted (compared to unittest.proto) because proto2 enums are not allowed + // inside proto2 messages. + // + // optional protobuf_unittest_import.ImportEnum optional_import_enum = 23; + optional string optional_string_piece = 24 [ctype=STRING_PIECE]; optional string optional_cord = 25 [ctype=CORD]; @@ -118,6 +124,11 @@ message TestAllTypes { repeated NestedEnum repeated_nested_enum = 51; repeated ForeignEnum repeated_foreign_enum = 52; + // Omitted (compared to unittest.proto) because proto2 enums are not allowed + // inside proto2 messages. + // + // repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53; + repeated string repeated_string_piece = 54 [ctype=STRING_PIECE]; repeated string repeated_cord = 55 [ctype=CORD]; @@ -131,6 +142,31 @@ message TestAllTypes { } } +// Test messages for packed fields + +message TestPackedTypes { + repeated int32 packed_int32 = 90 [packed = true]; + repeated int64 packed_int64 = 91 [packed = true]; + repeated uint32 packed_uint32 = 92 [packed = true]; + repeated uint64 packed_uint64 = 93 [packed = true]; + repeated sint32 packed_sint32 = 94 [packed = true]; + repeated sint64 packed_sint64 = 95 [packed = true]; + repeated fixed32 packed_fixed32 = 96 [packed = true]; + repeated fixed64 packed_fixed64 = 97 [packed = true]; + repeated sfixed32 packed_sfixed32 = 98 [packed = true]; + repeated sfixed64 packed_sfixed64 = 99 [packed = true]; + repeated float packed_float = 100 [packed = true]; + repeated double packed_double = 101 [packed = true]; + repeated bool packed_bool = 102 [packed = true]; + repeated ForeignEnum packed_enum = 103 [packed = true]; +} + +// This proto includes a recusively nested message. +message NestedTestAllTypes { + NestedTestAllTypes child = 1; + TestAllTypes payload = 2; +} + // Define these after TestAllTypes to make sure the compiler can handle // that. message ForeignMessage { @@ -138,7 +174,13 @@ message ForeignMessage { } enum ForeignEnum { - FOREIGN_FOO = 0; - FOREIGN_BAR = 1; - FOREIGN_BAZ = 2; + FOREIGN_ZERO = 0; + FOREIGN_FOO = 4; + FOREIGN_BAR = 5; + FOREIGN_BAZ = 6; +} + +// TestEmptyMessage is used to test behavior of unknown fields. +message TestEmptyMessage { } + diff --git a/src/google/protobuf/unknown_enum_impl.h b/src/google/protobuf/unknown_enum_impl.h index fb5380aa..39c10cbc 100644 --- a/src/google/protobuf/unknown_enum_impl.h +++ b/src/google/protobuf/unknown_enum_impl.h @@ -99,6 +99,29 @@ bool GetRepeatedEnumUnknowns_Template( } // NOTE: You should not call these functions directly. Instead use +// CLEAR_UNKNOWN_ENUM(), defined in the public header. The macro-versions +// operate in a type-safe manner and behave appropriately for the proto +// version of the message, whereas these versions assume a specific proto +// version and allow the caller to pass in any arbitrary integer value as a +// field number. +// +// Clears the unknown entries of the given field of the message. +void ClearUnknownEnum(Message* message, int32 field_number); +// In proto1, clears the field if the value is out of range. +// TODO(karner): Delete this or make it proto2-only once the migration +// to proto2 is complete. +void ClearUnknownEnumProto1(Message* message, int32 field_number); +template <typename T> +void ClearUnknownEnum_Template(T* message, int32 field_number) { + if (internal::is_base_of<bridge::internal::Proto1CompatibleMessage, T>::value || + !internal::is_base_of<ProtocolMessage, T>::value) { + ClearUnknownEnum(message, field_number); + } else { + ClearUnknownEnumProto1(message, field_number); + } +} + +// NOTE: You should not call these functions directly. Instead use // SET_UNKNOWN_ENUM(), defined in the public header. The macro-versions // operate in a type-safe manner and behave appropriately for the proto // version of the message, whereas these versions assume a specific proto diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h index 6f7a9fdb..987b1979 100644 --- a/src/google/protobuf/unknown_field_set.h +++ b/src/google/protobuf/unknown_field_set.h @@ -222,15 +222,17 @@ class LIBPROTOBUF_EXPORT UnknownField { // UnknownField is being created. inline void SetType(Type type); + union LengthDelimited { + string* string_value_; + }; + uint32 number_; uint32 type_; union { uint64 varint_; uint32 fixed32_; uint64 fixed64_; - mutable union { - string* string_value_; - } length_delimited_; + mutable union LengthDelimited length_delimited_; UnknownFieldSet* group_; }; }; diff --git a/src/google/protobuf/unknown_field_set_unittest.cc b/src/google/protobuf/unknown_field_set_unittest.cc index 6bba8fc7..9b02f0b0 100644 --- a/src/google/protobuf/unknown_field_set_unittest.cc +++ b/src/google/protobuf/unknown_field_set_unittest.cc @@ -485,7 +485,7 @@ TEST_F(UnknownFieldSetTest, UnknownEnumValue) { TEST_F(UnknownFieldSetTest, SpaceUsedExcludingSelf) { UnknownFieldSet empty; empty.AddVarint(1, 0); - EXPECT_EQ(/* vector<UnknownField> */ 24 + /* sizeof(UnknownField) */ 16, + EXPECT_EQ(sizeof(vector<UnknownField>) + sizeof(UnknownField), empty.SpaceUsedExcludingSelf()); } diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc index f4f02157..c5bbbf2e 100644 --- a/src/google/protobuf/wire_format.cc +++ b/src/google/protobuf/wire_format.cc @@ -141,7 +141,7 @@ bool WireFormat::SkipField(io::CodedInputStream* input, uint32 tag, bool WireFormat::SkipMessage(io::CodedInputStream* input, UnknownFieldSet* unknown_fields) { - while(true) { + while (true) { uint32 tag = input->ReadTag(); if (tag == 0) { // End of input. This is a valid place to end, so return true. @@ -159,6 +159,31 @@ bool WireFormat::SkipMessage(io::CodedInputStream* input, } } +bool WireFormat::ReadPackedEnumPreserveUnknowns(io::CodedInputStream* input, + uint32 field_number, + bool (*is_valid)(int), + UnknownFieldSet* unknown_fields, + RepeatedField<int>* values) { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + io::CodedInputStream::Limit limit = input->PushLimit(length); + while (input->BytesUntilLimit() > 0) { + int value; + if (!google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, WireFormatLite::TYPE_ENUM>(input, &value)) { + return false; + } + if (is_valid == NULL || is_valid(value)) { + values->Add(value); + } else { + unknown_fields->AddVarint(field_number, value); + } + } + input->PopLimit(limit); + return true; +} + + void WireFormat::SerializeUnknownFields(const UnknownFieldSet& unknown_fields, io::CodedOutputStream* output) { for (int i = 0; i < unknown_fields.field_count(); i++) { @@ -520,6 +545,14 @@ bool WireFormat::ParseAndMergeField( field->enum_type()->FindValueByNumber(value); if (enum_value != NULL) { message_reflection->AddEnum(message, field, enum_value); + } else { + // The enum value is not one of the known values. Add it to the + // UnknownFieldSet. + int64 sign_extended_value = static_cast<int64>(value); + message_reflection->MutableUnknownFields(message) + ->AddVarint( + WireFormatLite::GetTagFieldNumber(tag), + sign_extended_value); } } } diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h index 9f26eb29..8de491a6 100644 --- a/src/google/protobuf/wire_format.h +++ b/src/google/protobuf/wire_format.h @@ -138,6 +138,14 @@ class LIBPROTOBUF_EXPORT WireFormat { static bool SkipMessage(io::CodedInputStream* input, UnknownFieldSet* unknown_fields); + // Read a packed enum field. If the is_valid function is not NULL, values for + // which is_valid(value) returns false are appended to unknown_fields_stream. + static bool ReadPackedEnumPreserveUnknowns(io::CodedInputStream* input, + uint32 field_number, + bool (*is_valid)(int), + UnknownFieldSet* unknown_fields, + RepeatedField<int>* values); + // Write the contents of an UnknownFieldSet to the output. static void SerializeUnknownFields(const UnknownFieldSet& unknown_fields, io::CodedOutputStream* output); diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc index 50616551..2ce4920c 100644 --- a/src/google/protobuf/wire_format_lite.cc +++ b/src/google/protobuf/wire_format_lite.cc @@ -304,6 +304,34 @@ bool WireFormatLite::ReadPackedEnumNoInline(io::CodedInputStream* input, return true; } +bool WireFormatLite::ReadPackedEnumPreserveUnknowns( + io::CodedInputStream* input, + int field_number, + bool (*is_valid)(int), + io::CodedOutputStream* unknown_fields_stream, + RepeatedField<int>* values) { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + io::CodedInputStream::Limit limit = input->PushLimit(length); + while (input->BytesUntilLimit() > 0) { + int value; + if (!google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, WireFormatLite::TYPE_ENUM>(input, &value)) { + return false; + } + if (is_valid == NULL || is_valid(value)) { + values->Add(value); + } else { + uint32 tag = WireFormatLite::MakeTag(field_number, + WireFormatLite::WIRETYPE_VARINT); + unknown_fields_stream->WriteVarint32(tag); + unknown_fields_stream->WriteVarint32(value); + } + } + input->PopLimit(limit); + return true; +} + void WireFormatLite::WriteInt32(int field_number, int32 value, io::CodedOutputStream* output) { WriteTag(field_number, WIRETYPE_VARINT, output); diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h index acf88ead..76bc75a1 100644 --- a/src/google/protobuf/wire_format_lite.h +++ b/src/google/protobuf/wire_format_lite.h @@ -291,11 +291,20 @@ class LIBPROTOBUF_EXPORT WireFormatLite { template <typename CType, enum FieldType DeclaredType> static bool ReadPackedPrimitiveNoInline(input, RepeatedField<CType>* value); - // Read a packed enum field. Values for which is_valid() returns false are - // dropped. If is_valid == NULL, no values are dropped. + // Read a packed enum field. If the is_valid function is not NULL, values for + // which is_valid(value) returns false are silently dropped. static bool ReadPackedEnumNoInline(input, bool (*is_valid)(int), - RepeatedField<int>* value); + RepeatedField<int>* values); + + // Read a packed enum field. If the is_valid function is not NULL, values for + // which is_valid(value) returns false are appended to unknown_fields_stream. + static bool ReadPackedEnumPreserveUnknowns( + input, + field_number, + bool (*is_valid)(int), + io::CodedOutputStream* unknown_fields_stream, + RepeatedField<int>* values); // Read a string. ReadString(..., string* value) requires an existing string. static inline bool ReadString(input, string* value); @@ -647,7 +656,7 @@ inline double WireFormatLite::DecodeDouble(uint64 value) { inline uint32 WireFormatLite::ZigZagEncode32(int32 n) { // Note: the right-shift must be arithmetic - return (n << 1) ^ (n >> 31); + return (static_cast<uint32>(n) << 1) ^ (n >> 31); } inline int32 WireFormatLite::ZigZagDecode32(uint32 n) { @@ -656,7 +665,7 @@ inline int32 WireFormatLite::ZigZagDecode32(uint32 n) { inline uint64 WireFormatLite::ZigZagEncode64(int64 n) { // Note: the right-shift must be arithmetic - return (n << 1) ^ (n >> 63); + return (static_cast<uint64>(n) << 1) ^ (n >> 63); } inline int64 WireFormatLite::ZigZagDecode64(uint64 n) { diff --git a/src/google/protobuf/wrappers.proto b/src/google/protobuf/wrappers.proto new file mode 100644 index 00000000..4c902d44 --- /dev/null +++ b/src/google/protobuf/wrappers.proto @@ -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. + +// Wrappers for primitive (non-message) types. These types are useful +// for embedding primitives in the `google.protobuf.Any` type and for places +// where we need to distinguish between the absence of a primitive +// typed field and its default value. + +syntax = "proto3"; + +package google.protobuf; + +option java_multiple_files = true; +option java_outer_classname = "WrappersProto"; +option java_package = "com.google.protobuf"; +option objc_class_prefix = "GPB"; + + +// Wrapper message for double. +message DoubleValue { + // The double value. + double value = 1; +} + +// Wrapper message for float. +message FloatValue { + // The float value. + float value = 1; +} + +// Wrapper message for int64. +message Int64Value { + // The int64 value. + int64 value = 1; +} + +// Wrapper message for uint64. +message UInt64Value { + // The uint64 value. + uint64 value = 1; +} + +// Wrapper message for int32. +message Int32Value { + // The int32 value. + int32 value = 1; +} + +// Wrapper message for uint32. +message UInt32Value { + // The uint32 value. + uint32 value = 1; +} + +// Wrapper message for bool. +message BoolValue { + // The bool value. + bool value = 1; +} + +// Wrapper message for string. +message StringValue { + // The string value. + string value = 1; +} + +// Wrapper message for bytes. +message BytesValue { + // The bytes value. + bytes value = 1; +} |