mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2026-10-10 03:43:06 +08:00
Update protobuf version and protos
This commit is contained in:
@@ -1,395 +0,0 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
if HAVE_ZLIB
|
||||
GZCHECKPROGRAMS = zcgzip zcgunzip
|
||||
GZHEADERS = google/protobuf/io/gzip_stream.h
|
||||
GZTESTS = google/protobuf/io/gzip_stream_unittest.sh
|
||||
else
|
||||
GZCHECKPROGRAMS =
|
||||
GZHEADERS =
|
||||
GZTESTS =
|
||||
endif
|
||||
|
||||
if GCC
|
||||
# These are good warnings to turn on by default
|
||||
NO_OPT_CXXFLAGS = $(PTHREAD_CFLAGS) -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare
|
||||
else
|
||||
NO_OPT_CXXFLAGS = $(PTHREAD_CFLAGS)
|
||||
endif
|
||||
|
||||
AM_CXXFLAGS = $(NO_OPT_CXXFLAGS) $(PROTOBUF_OPT_FLAG)
|
||||
|
||||
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 \
|
||||
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 \
|
||||
testzip.jar testzip.list testzip.proto testzip.zip
|
||||
|
||||
MAINTAINERCLEANFILES = \
|
||||
Makefile.in
|
||||
|
||||
nobase_include_HEADERS = \
|
||||
google/protobuf/stubs/atomicops.h \
|
||||
google/protobuf/stubs/atomicops_internals_arm_gcc.h \
|
||||
google/protobuf/stubs/atomicops_internals_arm_qnx.h \
|
||||
google/protobuf/stubs/atomicops_internals_atomicword_compat.h \
|
||||
google/protobuf/stubs/atomicops_internals_macosx.h \
|
||||
google/protobuf/stubs/atomicops_internals_mips_gcc.h \
|
||||
google/protobuf/stubs/atomicops_internals_pnacl.h \
|
||||
google/protobuf/stubs/atomicops_internals_x86_gcc.h \
|
||||
google/protobuf/stubs/atomicops_internals_x86_msvc.h \
|
||||
google/protobuf/stubs/common.h \
|
||||
google/protobuf/stubs/platform_macros.h \
|
||||
google/protobuf/stubs/once.h \
|
||||
google/protobuf/stubs/template_util.h \
|
||||
google/protobuf/stubs/type_traits.h \
|
||||
google/protobuf/descriptor.h \
|
||||
google/protobuf/descriptor.pb.h \
|
||||
google/protobuf/descriptor_database.h \
|
||||
google/protobuf/dynamic_message.h \
|
||||
google/protobuf/extension_set.h \
|
||||
google/protobuf/generated_enum_reflection.h \
|
||||
google/protobuf/generated_message_util.h \
|
||||
google/protobuf/generated_message_reflection.h \
|
||||
google/protobuf/message.h \
|
||||
google/protobuf/message_lite.h \
|
||||
google/protobuf/reflection_ops.h \
|
||||
google/protobuf/repeated_field.h \
|
||||
google/protobuf/service.h \
|
||||
google/protobuf/text_format.h \
|
||||
google/protobuf/unknown_field_set.h \
|
||||
google/protobuf/wire_format.h \
|
||||
google/protobuf/wire_format_lite.h \
|
||||
google/protobuf/wire_format_lite_inl.h \
|
||||
google/protobuf/io/coded_stream.h \
|
||||
$(GZHEADERS) \
|
||||
google/protobuf/io/printer.h \
|
||||
google/protobuf/io/tokenizer.h \
|
||||
google/protobuf/io/zero_copy_stream.h \
|
||||
google/protobuf/io/zero_copy_stream_impl.h \
|
||||
google/protobuf/io/zero_copy_stream_impl_lite.h \
|
||||
google/protobuf/compiler/code_generator.h \
|
||||
google/protobuf/compiler/command_line_interface.h \
|
||||
google/protobuf/compiler/importer.h \
|
||||
google/protobuf/compiler/parser.h \
|
||||
google/protobuf/compiler/plugin.h \
|
||||
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
|
||||
|
||||
lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la
|
||||
|
||||
libprotobuf_lite_la_LIBADD = $(PTHREAD_LIBS)
|
||||
libprotobuf_lite_la_LDFLAGS = -version-info 8:0:0 -export-dynamic -no-undefined
|
||||
libprotobuf_lite_la_SOURCES = \
|
||||
google/protobuf/stubs/atomicops_internals_x86_gcc.cc \
|
||||
google/protobuf/stubs/atomicops_internals_x86_msvc.cc \
|
||||
google/protobuf/stubs/common.cc \
|
||||
google/protobuf/stubs/once.cc \
|
||||
google/protobuf/stubs/hash.h \
|
||||
google/protobuf/stubs/map-util.h \
|
||||
google/protobuf/stubs/stl_util.h \
|
||||
google/protobuf/stubs/stringprintf.cc \
|
||||
google/protobuf/stubs/stringprintf.h \
|
||||
google/protobuf/extension_set.cc \
|
||||
google/protobuf/generated_message_util.cc \
|
||||
google/protobuf/message_lite.cc \
|
||||
google/protobuf/repeated_field.cc \
|
||||
google/protobuf/wire_format_lite.cc \
|
||||
google/protobuf/io/coded_stream.cc \
|
||||
google/protobuf/io/coded_stream_inl.h \
|
||||
google/protobuf/io/zero_copy_stream.cc \
|
||||
google/protobuf/io/zero_copy_stream_impl_lite.cc
|
||||
|
||||
libprotobuf_la_LIBADD = $(PTHREAD_LIBS)
|
||||
libprotobuf_la_LDFLAGS = -version-info 8:0:0 -export-dynamic -no-undefined
|
||||
libprotobuf_la_SOURCES = \
|
||||
$(libprotobuf_lite_la_SOURCES) \
|
||||
google/protobuf/stubs/strutil.cc \
|
||||
google/protobuf/stubs/strutil.h \
|
||||
google/protobuf/stubs/substitute.cc \
|
||||
google/protobuf/stubs/substitute.h \
|
||||
google/protobuf/stubs/structurally_valid.cc \
|
||||
google/protobuf/descriptor.cc \
|
||||
google/protobuf/descriptor.pb.cc \
|
||||
google/protobuf/descriptor_database.cc \
|
||||
google/protobuf/dynamic_message.cc \
|
||||
google/protobuf/extension_set_heavy.cc \
|
||||
google/protobuf/generated_message_reflection.cc \
|
||||
google/protobuf/message.cc \
|
||||
google/protobuf/reflection_ops.cc \
|
||||
google/protobuf/service.cc \
|
||||
google/protobuf/text_format.cc \
|
||||
google/protobuf/unknown_field_set.cc \
|
||||
google/protobuf/wire_format.cc \
|
||||
google/protobuf/io/gzip_stream.cc \
|
||||
google/protobuf/io/printer.cc \
|
||||
google/protobuf/io/tokenizer.cc \
|
||||
google/protobuf/io/zero_copy_stream_impl.cc \
|
||||
google/protobuf/compiler/importer.cc \
|
||||
google/protobuf/compiler/parser.cc
|
||||
|
||||
libprotoc_la_LIBADD = $(PTHREAD_LIBS) libprotobuf.la
|
||||
libprotoc_la_LDFLAGS = -version-info 8:0:0 -export-dynamic -no-undefined
|
||||
libprotoc_la_SOURCES = \
|
||||
google/protobuf/compiler/code_generator.cc \
|
||||
google/protobuf/compiler/command_line_interface.cc \
|
||||
google/protobuf/compiler/plugin.cc \
|
||||
google/protobuf/compiler/plugin.pb.cc \
|
||||
google/protobuf/compiler/subprocess.cc \
|
||||
google/protobuf/compiler/subprocess.h \
|
||||
google/protobuf/compiler/zip_writer.cc \
|
||||
google/protobuf/compiler/zip_writer.h \
|
||||
google/protobuf/compiler/cpp/cpp_enum.cc \
|
||||
google/protobuf/compiler/cpp/cpp_enum.h \
|
||||
google/protobuf/compiler/cpp/cpp_enum_field.cc \
|
||||
google/protobuf/compiler/cpp/cpp_enum_field.h \
|
||||
google/protobuf/compiler/cpp/cpp_extension.cc \
|
||||
google/protobuf/compiler/cpp/cpp_extension.h \
|
||||
google/protobuf/compiler/cpp/cpp_field.cc \
|
||||
google/protobuf/compiler/cpp/cpp_field.h \
|
||||
google/protobuf/compiler/cpp/cpp_file.cc \
|
||||
google/protobuf/compiler/cpp/cpp_file.h \
|
||||
google/protobuf/compiler/cpp/cpp_generator.cc \
|
||||
google/protobuf/compiler/cpp/cpp_helpers.cc \
|
||||
google/protobuf/compiler/cpp/cpp_helpers.h \
|
||||
google/protobuf/compiler/cpp/cpp_message.cc \
|
||||
google/protobuf/compiler/cpp/cpp_message.h \
|
||||
google/protobuf/compiler/cpp/cpp_message_field.cc \
|
||||
google/protobuf/compiler/cpp/cpp_message_field.h \
|
||||
google/protobuf/compiler/cpp/cpp_options.h \
|
||||
google/protobuf/compiler/cpp/cpp_primitive_field.cc \
|
||||
google/protobuf/compiler/cpp/cpp_primitive_field.h \
|
||||
google/protobuf/compiler/cpp/cpp_service.cc \
|
||||
google/protobuf/compiler/cpp/cpp_service.h \
|
||||
google/protobuf/compiler/cpp/cpp_string_field.cc \
|
||||
google/protobuf/compiler/cpp/cpp_string_field.h \
|
||||
google/protobuf/compiler/java/java_enum.cc \
|
||||
google/protobuf/compiler/java/java_enum.h \
|
||||
google/protobuf/compiler/java/java_enum_field.cc \
|
||||
google/protobuf/compiler/java/java_enum_field.h \
|
||||
google/protobuf/compiler/java/java_extension.cc \
|
||||
google/protobuf/compiler/java/java_extension.h \
|
||||
google/protobuf/compiler/java/java_field.cc \
|
||||
google/protobuf/compiler/java/java_field.h \
|
||||
google/protobuf/compiler/java/java_file.cc \
|
||||
google/protobuf/compiler/java/java_file.h \
|
||||
google/protobuf/compiler/java/java_generator.cc \
|
||||
google/protobuf/compiler/java/java_helpers.cc \
|
||||
google/protobuf/compiler/java/java_helpers.h \
|
||||
google/protobuf/compiler/java/java_message.cc \
|
||||
google/protobuf/compiler/java/java_message.h \
|
||||
google/protobuf/compiler/java/java_message_field.cc \
|
||||
google/protobuf/compiler/java/java_message_field.h \
|
||||
google/protobuf/compiler/java/java_primitive_field.cc \
|
||||
google/protobuf/compiler/java/java_primitive_field.h \
|
||||
google/protobuf/compiler/java/java_service.cc \
|
||||
google/protobuf/compiler/java/java_service.h \
|
||||
google/protobuf/compiler/java/java_string_field.cc \
|
||||
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
|
||||
|
||||
bin_PROGRAMS = protoc
|
||||
protoc_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la
|
||||
protoc_SOURCES = google/protobuf/compiler/main.cc
|
||||
|
||||
# Tests ==============================================================
|
||||
|
||||
protoc_inputs = \
|
||||
google/protobuf/unittest.proto \
|
||||
google/protobuf/unittest_empty.proto \
|
||||
google/protobuf/unittest_import.proto \
|
||||
google/protobuf/unittest_import_public.proto \
|
||||
google/protobuf/unittest_mset.proto \
|
||||
google/protobuf/unittest_optimize_for.proto \
|
||||
google/protobuf/unittest_embed_optimize_for.proto \
|
||||
google/protobuf/unittest_custom_options.proto \
|
||||
google/protobuf/unittest_lite.proto \
|
||||
google/protobuf/unittest_import_lite.proto \
|
||||
google/protobuf/unittest_import_public_lite.proto \
|
||||
google/protobuf/unittest_lite_imports_nonlite.proto \
|
||||
google/protobuf/unittest_no_generic_services.proto \
|
||||
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(protoc_inputs) \
|
||||
solaris/libstdc++.la \
|
||||
google/protobuf/io/gzip_stream.h \
|
||||
google/protobuf/io/gzip_stream_unittest.sh \
|
||||
google/protobuf/testdata/golden_message \
|
||||
google/protobuf/testdata/golden_packed_fields_message \
|
||||
google/protobuf/testdata/text_format_unittest_data.txt \
|
||||
google/protobuf/testdata/text_format_unittest_extensions_data.txt \
|
||||
google/protobuf/package_info.h \
|
||||
google/protobuf/io/package_info.h \
|
||||
google/protobuf/compiler/package_info.h \
|
||||
google/protobuf/compiler/zip_output_unittest.sh \
|
||||
google/protobuf/unittest_enormous_descriptor.proto
|
||||
|
||||
protoc_lite_outputs = \
|
||||
google/protobuf/unittest_lite.pb.cc \
|
||||
google/protobuf/unittest_lite.pb.h \
|
||||
google/protobuf/unittest_import_lite.pb.cc \
|
||||
google/protobuf/unittest_import_lite.pb.h \
|
||||
google/protobuf/unittest_import_public_lite.pb.cc \
|
||||
google/protobuf/unittest_import_public_lite.pb.h
|
||||
|
||||
protoc_outputs = \
|
||||
$(protoc_lite_outputs) \
|
||||
google/protobuf/unittest.pb.cc \
|
||||
google/protobuf/unittest.pb.h \
|
||||
google/protobuf/unittest_empty.pb.cc \
|
||||
google/protobuf/unittest_empty.pb.h \
|
||||
google/protobuf/unittest_import.pb.cc \
|
||||
google/protobuf/unittest_import.pb.h \
|
||||
google/protobuf/unittest_import_public.pb.cc \
|
||||
google/protobuf/unittest_import_public.pb.h \
|
||||
google/protobuf/unittest_mset.pb.cc \
|
||||
google/protobuf/unittest_mset.pb.h \
|
||||
google/protobuf/unittest_optimize_for.pb.cc \
|
||||
google/protobuf/unittest_optimize_for.pb.h \
|
||||
google/protobuf/unittest_embed_optimize_for.pb.cc \
|
||||
google/protobuf/unittest_embed_optimize_for.pb.h \
|
||||
google/protobuf/unittest_custom_options.pb.cc \
|
||||
google/protobuf/unittest_custom_options.pb.h \
|
||||
google/protobuf/unittest_lite_imports_nonlite.pb.cc \
|
||||
google/protobuf/unittest_lite_imports_nonlite.pb.h \
|
||||
google/protobuf/unittest_no_generic_services.pb.cc \
|
||||
google/protobuf/unittest_no_generic_services.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)
|
||||
|
||||
if USE_EXTERNAL_PROTOC
|
||||
|
||||
unittest_proto_middleman: $(protoc_inputs)
|
||||
$(PROTOC) -I$(srcdir) --cpp_out=. $^
|
||||
touch unittest_proto_middleman
|
||||
|
||||
else
|
||||
|
||||
# We have to cd to $(srcdir) before executing protoc because $(protoc_inputs) is
|
||||
# relative to srcdir, which may not be the same as the current directory when
|
||||
# building out-of-tree.
|
||||
unittest_proto_middleman: protoc$(EXEEXT) $(protoc_inputs)
|
||||
oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/protoc$(EXEEXT) -I. --cpp_out=$$oldpwd $(protoc_inputs) )
|
||||
touch unittest_proto_middleman
|
||||
|
||||
endif
|
||||
|
||||
$(protoc_outputs): unittest_proto_middleman
|
||||
|
||||
COMMON_TEST_SOURCES = \
|
||||
google/protobuf/test_util.cc \
|
||||
google/protobuf/test_util.h \
|
||||
google/protobuf/testing/googletest.cc \
|
||||
google/protobuf/testing/googletest.h \
|
||||
google/protobuf/testing/file.cc \
|
||||
google/protobuf/testing/file.h
|
||||
|
||||
check_PROGRAMS = protoc protobuf-test protobuf-lazy-descriptor-test \
|
||||
protobuf-lite-test test_plugin $(GZCHECKPROGRAMS)
|
||||
protobuf_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \
|
||||
$(top_builddir)/gtest/lib/libgtest.la \
|
||||
$(top_builddir)/gtest/lib/libgtest_main.la
|
||||
protobuf_test_CPPFLAGS = -I$(top_srcdir)/gtest/include \
|
||||
-I$(top_builddir)/gtest/include
|
||||
# Disable optimization for tests unless the user explicitly asked for it,
|
||||
# since test_util.cc takes forever to compile with optimization (with GCC).
|
||||
# See configure.ac for more info.
|
||||
protobuf_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
|
||||
protobuf_test_SOURCES = \
|
||||
google/protobuf/stubs/common_unittest.cc \
|
||||
google/protobuf/stubs/once_unittest.cc \
|
||||
google/protobuf/stubs/strutil_unittest.cc \
|
||||
google/protobuf/stubs/structurally_valid_unittest.cc \
|
||||
google/protobuf/stubs/stringprintf_unittest.cc \
|
||||
google/protobuf/stubs/template_util_unittest.cc \
|
||||
google/protobuf/stubs/type_traits_unittest.cc \
|
||||
google/protobuf/descriptor_database_unittest.cc \
|
||||
google/protobuf/descriptor_unittest.cc \
|
||||
google/protobuf/dynamic_message_unittest.cc \
|
||||
google/protobuf/extension_set_unittest.cc \
|
||||
google/protobuf/generated_message_reflection_unittest.cc \
|
||||
google/protobuf/message_unittest.cc \
|
||||
google/protobuf/reflection_ops_unittest.cc \
|
||||
google/protobuf/repeated_field_unittest.cc \
|
||||
google/protobuf/repeated_field_reflection_unittest.cc \
|
||||
google/protobuf/text_format_unittest.cc \
|
||||
google/protobuf/unknown_field_set_unittest.cc \
|
||||
google/protobuf/wire_format_unittest.cc \
|
||||
google/protobuf/io/coded_stream_unittest.cc \
|
||||
google/protobuf/io/printer_unittest.cc \
|
||||
google/protobuf/io/tokenizer_unittest.cc \
|
||||
google/protobuf/io/zero_copy_stream_unittest.cc \
|
||||
google/protobuf/compiler/command_line_interface_unittest.cc \
|
||||
google/protobuf/compiler/importer_unittest.cc \
|
||||
google/protobuf/compiler/mock_code_generator.cc \
|
||||
google/protobuf/compiler/mock_code_generator.h \
|
||||
google/protobuf/compiler/parser_unittest.cc \
|
||||
google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc \
|
||||
google/protobuf/compiler/cpp/cpp_unittest.h \
|
||||
google/protobuf/compiler/cpp/cpp_unittest.cc \
|
||||
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/python/python_plugin_unittest.cc \
|
||||
$(COMMON_TEST_SOURCES)
|
||||
nodist_protobuf_test_SOURCES = $(protoc_outputs)
|
||||
|
||||
# Run cpp_unittest again with PROTOBUF_TEST_NO_DESCRIPTORS defined.
|
||||
protobuf_lazy_descriptor_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la \
|
||||
$(top_builddir)/gtest/lib/libgtest.la \
|
||||
$(top_builddir)/gtest/lib/libgtest_main.la
|
||||
protobuf_lazy_descriptor_test_CPPFLAGS = -I$(top_srcdir)/gtest/include \
|
||||
-I$(top_builddir)/gtest/include \
|
||||
-DPROTOBUF_TEST_NO_DESCRIPTORS
|
||||
protobuf_lazy_descriptor_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
|
||||
protobuf_lazy_descriptor_test_SOURCES = \
|
||||
google/protobuf/compiler/cpp/cpp_unittest.cc \
|
||||
$(COMMON_TEST_SOURCES)
|
||||
nodist_protobuf_lazy_descriptor_test_SOURCES = $(protoc_outputs)
|
||||
|
||||
# Build lite_unittest separately, since it doesn't use gtest.
|
||||
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/test_util_lite.cc \
|
||||
google/protobuf/test_util_lite.h
|
||||
nodist_protobuf_lite_test_SOURCES = $(protoc_lite_outputs)
|
||||
|
||||
# Test plugin binary.
|
||||
test_plugin_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \
|
||||
$(top_builddir)/gtest/lib/libgtest.la
|
||||
test_plugin_CPPFLAGS = -I$(top_srcdir)/gtest/include \
|
||||
-I$(top_builddir)/gtest/include
|
||||
test_plugin_SOURCES = \
|
||||
google/protobuf/compiler/mock_code_generator.cc \
|
||||
google/protobuf/testing/file.cc \
|
||||
google/protobuf/testing/file.h \
|
||||
google/protobuf/compiler/test_plugin.cc
|
||||
|
||||
if HAVE_ZLIB
|
||||
zcgzip_LDADD = $(PTHREAD_LIBS) libprotobuf.la
|
||||
zcgzip_SOURCES = google/protobuf/testing/zcgzip.cc
|
||||
|
||||
zcgunzip_LDADD = $(PTHREAD_LIBS) libprotobuf.la
|
||||
zcgunzip_SOURCES = google/protobuf/testing/zcgunzip.cc
|
||||
endif
|
||||
|
||||
TESTS = protobuf-test protobuf-lazy-descriptor-test protobuf-lite-test \
|
||||
google/protobuf/compiler/zip_output_unittest.sh $(GZTESTS)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,652 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_file.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_enum.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_service.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_extension.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_message.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_field.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 cpp {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
FileGenerator::FileGenerator(const FileDescriptor* file,
|
||||
const Options& options)
|
||||
: file_(file),
|
||||
message_generators_(
|
||||
new scoped_ptr<MessageGenerator>[file->message_type_count()]),
|
||||
enum_generators_(
|
||||
new scoped_ptr<EnumGenerator>[file->enum_type_count()]),
|
||||
service_generators_(
|
||||
new scoped_ptr<ServiceGenerator>[file->service_count()]),
|
||||
extension_generators_(
|
||||
new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
|
||||
options_(options) {
|
||||
|
||||
for (int i = 0; i < file->message_type_count(); i++) {
|
||||
message_generators_[i].reset(
|
||||
new MessageGenerator(file->message_type(i), options));
|
||||
}
|
||||
|
||||
for (int i = 0; i < file->enum_type_count(); i++) {
|
||||
enum_generators_[i].reset(
|
||||
new EnumGenerator(file->enum_type(i), options));
|
||||
}
|
||||
|
||||
for (int i = 0; i < file->service_count(); i++) {
|
||||
service_generators_[i].reset(
|
||||
new ServiceGenerator(file->service(i), options));
|
||||
}
|
||||
|
||||
for (int i = 0; i < file->extension_count(); i++) {
|
||||
extension_generators_[i].reset(
|
||||
new ExtensionGenerator(file->extension(i), options));
|
||||
}
|
||||
|
||||
SplitStringUsing(file_->package(), ".", &package_parts_);
|
||||
}
|
||||
|
||||
FileGenerator::~FileGenerator() {}
|
||||
|
||||
void FileGenerator::GenerateHeader(io::Printer* printer) {
|
||||
string filename_identifier = FilenameIdentifier(file_->name());
|
||||
|
||||
// Generate top of header.
|
||||
printer->Print(
|
||||
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
|
||||
"// source: $filename$\n"
|
||||
"\n"
|
||||
"#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
|
||||
"#define PROTOBUF_$filename_identifier$__INCLUDED\n"
|
||||
"\n"
|
||||
"#include <string>\n"
|
||||
"\n",
|
||||
"filename", file_->name(),
|
||||
"filename_identifier", filename_identifier);
|
||||
|
||||
|
||||
printer->Print(
|
||||
"#include <google/protobuf/stubs/common.h>\n"
|
||||
"\n");
|
||||
|
||||
// Verify the protobuf library header version is compatible with the protoc
|
||||
// version before going any further.
|
||||
printer->Print(
|
||||
"#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
|
||||
"#error This file was generated by a newer version of protoc which is\n"
|
||||
"#error incompatible with your Protocol Buffer headers. Please update\n"
|
||||
"#error your headers.\n"
|
||||
"#endif\n"
|
||||
"#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
|
||||
"#error This file was generated by an older version of protoc which is\n"
|
||||
"#error incompatible with your Protocol Buffer headers. Please\n"
|
||||
"#error regenerate this file with a newer version of protoc.\n"
|
||||
"#endif\n"
|
||||
"\n",
|
||||
"min_header_version",
|
||||
SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
|
||||
"protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
|
||||
|
||||
// OK, it's now safe to #include other files.
|
||||
printer->Print(
|
||||
"#include <google/protobuf/generated_message_util.h>\n");
|
||||
if (file_->message_type_count() > 0) {
|
||||
if (HasDescriptorMethods(file_)) {
|
||||
printer->Print(
|
||||
"#include <google/protobuf/message.h>\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
"#include <google/protobuf/message_lite.h>\n");
|
||||
}
|
||||
}
|
||||
printer->Print(
|
||||
"#include <google/protobuf/repeated_field.h>\n"
|
||||
"#include <google/protobuf/extension_set.h>\n");
|
||||
|
||||
if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) {
|
||||
printer->Print(
|
||||
"#include <google/protobuf/generated_enum_reflection.h>\n");
|
||||
}
|
||||
|
||||
if (HasGenericServices(file_)) {
|
||||
printer->Print(
|
||||
"#include <google/protobuf/service.h>\n");
|
||||
}
|
||||
|
||||
if (HasUnknownFields(file_) && file_->message_type_count() > 0) {
|
||||
printer->Print(
|
||||
"#include <google/protobuf/unknown_field_set.h>\n");
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < file_->dependency_count(); i++) {
|
||||
printer->Print(
|
||||
"#include \"$dependency$.pb.h\"\n",
|
||||
"dependency", StripProto(file_->dependency(i)->name()));
|
||||
}
|
||||
|
||||
|
||||
printer->Print(
|
||||
"// @@protoc_insertion_point(includes)\n");
|
||||
|
||||
|
||||
// Open namespace.
|
||||
GenerateNamespaceOpeners(printer);
|
||||
|
||||
// Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
|
||||
// functions, so that we can declare them to be friends of each class.
|
||||
printer->Print(
|
||||
"\n"
|
||||
"// Internal implementation detail -- do not call these.\n"
|
||||
"void $dllexport_decl$ $adddescriptorsname$();\n",
|
||||
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
|
||||
"dllexport_decl", options_.dllexport_decl);
|
||||
|
||||
printer->Print(
|
||||
// Note that we don't put dllexport_decl on these because they are only
|
||||
// called by the .pb.cc file in which they are defined.
|
||||
"void $assigndescriptorsname$();\n"
|
||||
"void $shutdownfilename$();\n"
|
||||
"\n",
|
||||
"assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
|
||||
"shutdownfilename", GlobalShutdownFileName(file_->name()));
|
||||
|
||||
// Generate forward declarations of classes.
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
message_generators_[i]->GenerateForwardDeclaration(printer);
|
||||
}
|
||||
|
||||
printer->Print("\n");
|
||||
|
||||
// Generate enum definitions.
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
message_generators_[i]->GenerateEnumDefinitions(printer);
|
||||
}
|
||||
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||
enum_generators_[i]->GenerateDefinition(printer);
|
||||
}
|
||||
|
||||
printer->Print(kThickSeparator);
|
||||
printer->Print("\n");
|
||||
|
||||
// Generate class definitions.
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
if (i > 0) {
|
||||
printer->Print("\n");
|
||||
printer->Print(kThinSeparator);
|
||||
printer->Print("\n");
|
||||
}
|
||||
message_generators_[i]->GenerateClassDefinition(printer);
|
||||
}
|
||||
|
||||
printer->Print("\n");
|
||||
printer->Print(kThickSeparator);
|
||||
printer->Print("\n");
|
||||
|
||||
if (HasGenericServices(file_)) {
|
||||
// Generate service definitions.
|
||||
for (int i = 0; i < file_->service_count(); i++) {
|
||||
if (i > 0) {
|
||||
printer->Print("\n");
|
||||
printer->Print(kThinSeparator);
|
||||
printer->Print("\n");
|
||||
}
|
||||
service_generators_[i]->GenerateDeclarations(printer);
|
||||
}
|
||||
|
||||
printer->Print("\n");
|
||||
printer->Print(kThickSeparator);
|
||||
printer->Print("\n");
|
||||
}
|
||||
|
||||
// Declare extension identifiers.
|
||||
for (int i = 0; i < file_->extension_count(); i++) {
|
||||
extension_generators_[i]->GenerateDeclaration(printer);
|
||||
}
|
||||
|
||||
printer->Print("\n");
|
||||
printer->Print(kThickSeparator);
|
||||
printer->Print("\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);
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"\n"
|
||||
"// @@protoc_insertion_point(namespace_scope)\n");
|
||||
|
||||
// Close up namespace.
|
||||
GenerateNamespaceClosers(printer);
|
||||
|
||||
// Emit GetEnumDescriptor specializations into google::protobuf namespace:
|
||||
if (HasDescriptorMethods(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>(); }
|
||||
// which appears in GetEnumDescriptor() specializations.
|
||||
printer->Print(
|
||||
"\n"
|
||||
"#ifndef SWIG\n"
|
||||
"namespace google {\nnamespace protobuf {\n"
|
||||
"\n");
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
|
||||
}
|
||||
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||
enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
|
||||
}
|
||||
printer->Print(
|
||||
"\n"
|
||||
"} // namespace google\n} // namespace protobuf\n"
|
||||
"#endif // SWIG\n");
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"\n"
|
||||
"// @@protoc_insertion_point(global_scope)\n"
|
||||
"\n");
|
||||
|
||||
printer->Print(
|
||||
"#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
|
||||
"filename_identifier", filename_identifier);
|
||||
}
|
||||
|
||||
void FileGenerator::GenerateSource(io::Printer* printer) {
|
||||
printer->Print(
|
||||
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
|
||||
"// source: $filename$\n"
|
||||
"\n"
|
||||
|
||||
// The generated code calls accessors that might be deprecated. We don't
|
||||
// want the compiler to warn in generated code.
|
||||
"#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
|
||||
"#include \"$basename$.pb.h\"\n"
|
||||
"\n"
|
||||
"#include <algorithm>\n" // for swap()
|
||||
"\n"
|
||||
"#include <google/protobuf/stubs/common.h>\n"
|
||||
"#include <google/protobuf/stubs/once.h>\n"
|
||||
"#include <google/protobuf/io/coded_stream.h>\n"
|
||||
"#include <google/protobuf/wire_format_lite_inl.h>\n",
|
||||
"filename", file_->name(),
|
||||
"basename", StripProto(file_->name()));
|
||||
|
||||
if (HasDescriptorMethods(file_)) {
|
||||
printer->Print(
|
||||
"#include <google/protobuf/descriptor.h>\n"
|
||||
"#include <google/protobuf/generated_message_reflection.h>\n"
|
||||
"#include <google/protobuf/reflection_ops.h>\n"
|
||||
"#include <google/protobuf/wire_format.h>\n");
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"// @@protoc_insertion_point(includes)\n");
|
||||
|
||||
GenerateNamespaceOpeners(printer);
|
||||
|
||||
if (HasDescriptorMethods(file_)) {
|
||||
printer->Print(
|
||||
"\n"
|
||||
"namespace {\n"
|
||||
"\n");
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
message_generators_[i]->GenerateDescriptorDeclarations(printer);
|
||||
}
|
||||
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||
printer->Print(
|
||||
"const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
|
||||
"name", ClassName(file_->enum_type(i), false));
|
||||
}
|
||||
|
||||
if (HasGenericServices(file_)) {
|
||||
for (int i = 0; i < file_->service_count(); i++) {
|
||||
printer->Print(
|
||||
"const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
|
||||
"name", file_->service(i)->name());
|
||||
}
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"\n"
|
||||
"} // namespace\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
// Define our externally-visible BuildDescriptors() function. (For the lite
|
||||
// library, all this does is initialize default instances.)
|
||||
GenerateBuildDescriptors(printer);
|
||||
|
||||
// Generate enums.
|
||||
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||
enum_generators_[i]->GenerateMethods(printer);
|
||||
}
|
||||
|
||||
// Generate classes.
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
printer->Print("\n");
|
||||
printer->Print(kThickSeparator);
|
||||
printer->Print("\n");
|
||||
message_generators_[i]->GenerateClassMethods(printer);
|
||||
}
|
||||
|
||||
if (HasGenericServices(file_)) {
|
||||
// Generate services.
|
||||
for (int i = 0; i < file_->service_count(); i++) {
|
||||
if (i == 0) printer->Print("\n");
|
||||
printer->Print(kThickSeparator);
|
||||
printer->Print("\n");
|
||||
service_generators_[i]->GenerateImplementation(printer);
|
||||
}
|
||||
}
|
||||
|
||||
// Define extensions.
|
||||
for (int i = 0; i < file_->extension_count(); i++) {
|
||||
extension_generators_[i]->GenerateDefinition(printer);
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"\n"
|
||||
"// @@protoc_insertion_point(namespace_scope)\n");
|
||||
|
||||
GenerateNamespaceClosers(printer);
|
||||
|
||||
printer->Print(
|
||||
"\n"
|
||||
"// @@protoc_insertion_point(global_scope)\n");
|
||||
}
|
||||
|
||||
void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
|
||||
// AddDescriptors() is a file-level procedure which adds the encoded
|
||||
// FileDescriptorProto for this .proto file to the global DescriptorPool for
|
||||
// generated files (DescriptorPool::generated_pool()). It either runs at
|
||||
// static initialization time (by default) or when default_instance() is
|
||||
// called for the first time (in LITE_RUNTIME mode with
|
||||
// GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER flag enabled). This procedure also
|
||||
// constructs default instances and registers extensions.
|
||||
//
|
||||
// Its sibling, AssignDescriptors(), actually pulls the compiled
|
||||
// FileDescriptor from the DescriptorPool and uses it to populate all of
|
||||
// the global variables which store pointers to the descriptor objects.
|
||||
// It also constructs the reflection objects. It is called the first time
|
||||
// anyone calls descriptor() or GetReflection() on one of the types defined
|
||||
// in the file.
|
||||
|
||||
// In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
|
||||
// and we only use AddDescriptors() to allocate default instances.
|
||||
if (HasDescriptorMethods(file_)) {
|
||||
printer->Print(
|
||||
"\n"
|
||||
"void $assigndescriptorsname$() {\n",
|
||||
"assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
|
||||
printer->Indent();
|
||||
|
||||
// Make sure the file has found its way into the pool. If a descriptor
|
||||
// is requested *during* static init then AddDescriptors() may not have
|
||||
// been called yet, so we call it manually. Note that it's fine if
|
||||
// AddDescriptors() is called multiple times.
|
||||
printer->Print(
|
||||
"$adddescriptorsname$();\n",
|
||||
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
|
||||
|
||||
// Get the file's descriptor from the pool.
|
||||
printer->Print(
|
||||
"const ::google::protobuf::FileDescriptor* file =\n"
|
||||
" ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n"
|
||||
" \"$filename$\");\n"
|
||||
// Note that this GOOGLE_CHECK is necessary to prevent a warning about "file"
|
||||
// being unused when compiling an empty .proto file.
|
||||
"GOOGLE_CHECK(file != NULL);\n",
|
||||
"filename", file_->name());
|
||||
|
||||
// Go through all the stuff defined in this file and generated code to
|
||||
// assign the global descriptor pointers based on the file descriptor.
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
message_generators_[i]->GenerateDescriptorInitializer(printer, i);
|
||||
}
|
||||
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||
enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
|
||||
}
|
||||
if (HasGenericServices(file_)) {
|
||||
for (int i = 0; i < file_->service_count(); i++) {
|
||||
service_generators_[i]->GenerateDescriptorInitializer(printer, i);
|
||||
}
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n"
|
||||
"\n");
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
// protobuf_AssignDescriptorsOnce(): The first time it is called, calls
|
||||
// AssignDescriptors(). All later times, waits for the first call to
|
||||
// complete and then returns.
|
||||
printer->Print(
|
||||
"namespace {\n"
|
||||
"\n"
|
||||
"GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
|
||||
"inline void protobuf_AssignDescriptorsOnce() {\n"
|
||||
" ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
|
||||
" &$assigndescriptorsname$);\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
|
||||
|
||||
// protobuf_RegisterTypes(): Calls
|
||||
// MessageFactory::InternalRegisterGeneratedType() for each message type.
|
||||
printer->Print(
|
||||
"void protobuf_RegisterTypes(const ::std::string&) {\n"
|
||||
" protobuf_AssignDescriptorsOnce();\n");
|
||||
printer->Indent();
|
||||
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
message_generators_[i]->GenerateTypeRegistrations(printer);
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n"
|
||||
"\n"
|
||||
"} // namespace\n");
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
// ShutdownFile(): Deletes descriptors, default instances, etc. on shutdown.
|
||||
printer->Print(
|
||||
"\n"
|
||||
"void $shutdownfilename$() {\n",
|
||||
"shutdownfilename", GlobalShutdownFileName(file_->name()));
|
||||
printer->Indent();
|
||||
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
message_generators_[i]->GenerateShutdownCode(printer);
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n\n");
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
// Now generate the AddDescriptors() function.
|
||||
PrintHandlingOptionalStaticInitializers(
|
||||
file_, printer,
|
||||
// With static initializers.
|
||||
// Note that we don't need any special synchronization in the following code
|
||||
// because it is called at static init time before any threads exist.
|
||||
"void $adddescriptorsname$() {\n"
|
||||
" static bool already_here = false;\n"
|
||||
" if (already_here) return;\n"
|
||||
" already_here = true;\n"
|
||||
" GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
|
||||
"\n",
|
||||
// Without.
|
||||
"void $adddescriptorsname$_impl() {\n"
|
||||
" GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
|
||||
"\n",
|
||||
// Vars.
|
||||
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
|
||||
|
||||
printer->Indent();
|
||||
|
||||
// Call the AddDescriptors() methods for all of our dependencies, to make
|
||||
// sure they get added first.
|
||||
for (int i = 0; i < file_->dependency_count(); i++) {
|
||||
const FileDescriptor* dependency = file_->dependency(i);
|
||||
// Print the namespace prefix for the dependency.
|
||||
vector<string> dependency_package_parts;
|
||||
SplitStringUsing(dependency->package(), ".", &dependency_package_parts);
|
||||
printer->Print("::");
|
||||
for (int j = 0; j < dependency_package_parts.size(); j++) {
|
||||
printer->Print("$name$::",
|
||||
"name", dependency_package_parts[j]);
|
||||
}
|
||||
// Call its AddDescriptors function.
|
||||
printer->Print(
|
||||
"$name$();\n",
|
||||
"name", GlobalAddDescriptorsName(dependency->name()));
|
||||
}
|
||||
|
||||
if (HasDescriptorMethods(file_)) {
|
||||
// Embed the descriptor. We simply serialize the entire FileDescriptorProto
|
||||
// and embed it as a string literal, which is parsed and built into real
|
||||
// descriptors at initialization time.
|
||||
FileDescriptorProto file_proto;
|
||||
file_->CopyTo(&file_proto);
|
||||
string file_data;
|
||||
file_proto.SerializeToString(&file_data);
|
||||
|
||||
printer->Print(
|
||||
"::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
|
||||
|
||||
// Only write 40 bytes per line.
|
||||
static const int kBytesPerLine = 40;
|
||||
for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
|
||||
printer->Print("\n \"$data$\"",
|
||||
"data",
|
||||
EscapeTrigraphs(
|
||||
CEscape(file_data.substr(i, kBytesPerLine))));
|
||||
}
|
||||
printer->Print(
|
||||
", $size$);\n",
|
||||
"size", SimpleItoa(file_data.size()));
|
||||
|
||||
// Call MessageFactory::InternalRegisterGeneratedFile().
|
||||
printer->Print(
|
||||
"::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
|
||||
" \"$filename$\", &protobuf_RegisterTypes);\n",
|
||||
"filename", file_->name());
|
||||
}
|
||||
|
||||
// Allocate and initialize default instances. This can't be done lazily
|
||||
// since default instances are returned by simple accessors and are used with
|
||||
// extensions. Speaking of which, we also register extensions at this time.
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
message_generators_[i]->GenerateDefaultInstanceAllocator(printer);
|
||||
}
|
||||
for (int i = 0; i < file_->extension_count(); i++) {
|
||||
extension_generators_[i]->GenerateRegistration(printer);
|
||||
}
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n",
|
||||
"shutdownfilename", GlobalShutdownFileName(file_->name()));
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n"
|
||||
"\n");
|
||||
|
||||
PrintHandlingOptionalStaticInitializers(
|
||||
file_, printer,
|
||||
// With static initializers.
|
||||
"// Force AddDescriptors() to be called at static initialization time.\n"
|
||||
"struct StaticDescriptorInitializer_$filename$ {\n"
|
||||
" StaticDescriptorInitializer_$filename$() {\n"
|
||||
" $adddescriptorsname$();\n"
|
||||
" }\n"
|
||||
"} static_descriptor_initializer_$filename$_;\n",
|
||||
// Without.
|
||||
"GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n"
|
||||
"void $adddescriptorsname$() {\n"
|
||||
" ::google::protobuf::::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n"
|
||||
" &$adddescriptorsname$_impl);\n"
|
||||
"}\n",
|
||||
// Vars.
|
||||
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
|
||||
"filename", FilenameIdentifier(file_->name()));
|
||||
}
|
||||
|
||||
void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) {
|
||||
if (package_parts_.size() > 0) printer->Print("\n");
|
||||
|
||||
for (int i = 0; i < package_parts_.size(); i++) {
|
||||
printer->Print("namespace $part$ {\n",
|
||||
"part", package_parts_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
|
||||
if (package_parts_.size() > 0) printer->Print("\n");
|
||||
|
||||
for (int i = package_parts_.size() - 1; i >= 0; i--) {
|
||||
printer->Print("} // namespace $part$\n",
|
||||
"part", package_parts_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -1,186 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace io {
|
||||
class Printer;
|
||||
}
|
||||
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
// Commonly-used separator comments. Thick is a line of '=', thin is a line
|
||||
// of '-'.
|
||||
extern const char kThickSeparator[];
|
||||
extern const char kThinSeparator[];
|
||||
|
||||
// Returns the non-nested type name for the given type. If "qualified" is
|
||||
// true, prefix the type with the full namespace. For example, if you had:
|
||||
// package foo.bar;
|
||||
// message Baz { message Qux {} }
|
||||
// Then the qualified ClassName for Qux would be:
|
||||
// ::foo::bar::Baz_Qux
|
||||
// While the non-qualified version would be:
|
||||
// Baz_Qux
|
||||
string ClassName(const Descriptor* descriptor, bool qualified);
|
||||
string ClassName(const EnumDescriptor* enum_descriptor, bool qualified);
|
||||
|
||||
string SuperClassName(const Descriptor* descriptor);
|
||||
|
||||
// Get the (unqualified) name that should be used for this field in C++ code.
|
||||
// The name is coerced to lower-case to emulate proto1 behavior. People
|
||||
// should be using lowercase-with-underscores style for proto field names
|
||||
// anyway, so normally this just returns field->name().
|
||||
string FieldName(const FieldDescriptor* field);
|
||||
|
||||
// Get the unqualified name that should be used for a field's field
|
||||
// number constant.
|
||||
string FieldConstantName(const FieldDescriptor *field);
|
||||
|
||||
// Returns the scope where the field was defined (for extensions, this is
|
||||
// different from the message type to which the field applies).
|
||||
inline const Descriptor* FieldScope(const FieldDescriptor* field) {
|
||||
return field->is_extension() ?
|
||||
field->extension_scope() : field->containing_type();
|
||||
}
|
||||
|
||||
// Returns the fully-qualified type name field->message_type(). Usually this
|
||||
// is just ClassName(field->message_type(), true);
|
||||
string FieldMessageTypeName(const FieldDescriptor* field);
|
||||
|
||||
// Strips ".proto" or ".protodevel" from the end of a filename.
|
||||
string StripProto(const string& filename);
|
||||
|
||||
// Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.).
|
||||
// Note: non-built-in type names will be qualified, meaning they will start
|
||||
// with a ::. If you are using the type as a template parameter, you will
|
||||
// need to insure there is a space between the < and the ::, because the
|
||||
// ridiculous C++ standard defines "<:" to be a synonym for "[".
|
||||
const char* PrimitiveTypeName(FieldDescriptor::CppType type);
|
||||
|
||||
// Get the declared type name in CamelCase format, as is used e.g. for the
|
||||
// methods of WireFormat. For example, TYPE_INT32 becomes "Int32".
|
||||
const char* DeclaredTypeMethodName(FieldDescriptor::Type type);
|
||||
|
||||
// Get code that evaluates to the field's default value.
|
||||
string DefaultValue(const FieldDescriptor* field);
|
||||
|
||||
// Convert a file name into a valid identifier.
|
||||
string FilenameIdentifier(const string& filename);
|
||||
|
||||
// Return the name of the AddDescriptors() function for a given file.
|
||||
string GlobalAddDescriptorsName(const string& filename);
|
||||
|
||||
// Return the name of the AssignDescriptors() function for a given file.
|
||||
string GlobalAssignDescriptorsName(const string& filename);
|
||||
|
||||
// Return the name of the ShutdownFile() function for a given file.
|
||||
string GlobalShutdownFileName(const string& filename);
|
||||
|
||||
// Escape C++ trigraphs by escaping question marks to \?
|
||||
string EscapeTrigraphs(const string& to_escape);
|
||||
|
||||
// Do message classes in this file keep track of unknown fields?
|
||||
inline bool HasUnknownFields(const FileDescriptor* file) {
|
||||
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
|
||||
|
||||
// Does this file have any enum type definitions?
|
||||
bool HasEnumDefinitions(const FileDescriptor* file);
|
||||
|
||||
// Does this file have generated parsing, serialization, and other
|
||||
// standard methods for which reflection-based fallback implementations exist?
|
||||
inline bool HasGeneratedMethods(const FileDescriptor* file) {
|
||||
return file->options().optimize_for() != FileOptions::CODE_SIZE;
|
||||
}
|
||||
|
||||
// Do message classes in this file have descriptor and reflection methods?
|
||||
inline bool HasDescriptorMethods(const FileDescriptor* file) {
|
||||
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
|
||||
// Should we generate generic services for this file?
|
||||
inline bool HasGenericServices(const FileDescriptor* file) {
|
||||
return file->service_count() > 0 &&
|
||||
file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
|
||||
file->options().cc_generic_services();
|
||||
}
|
||||
|
||||
// Should string fields in this file verify that their contents are UTF-8?
|
||||
inline bool HasUtf8Verification(const FileDescriptor* file) {
|
||||
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
|
||||
// Should we generate a separate, super-optimized code path for serializing to
|
||||
// flat arrays? We don't do this in Lite mode because we'd rather reduce code
|
||||
// size.
|
||||
inline bool HasFastArraySerialization(const FileDescriptor* file) {
|
||||
return file->options().optimize_for() == FileOptions::SPEED;
|
||||
}
|
||||
|
||||
// Returns whether we have to generate code with static initializers.
|
||||
bool StaticInitializersForced(const FileDescriptor* file);
|
||||
|
||||
// Prints 'with_static_init' if static initializers have to be used for the
|
||||
// provided file. Otherwise emits both 'with_static_init' and
|
||||
// 'without_static_init' using #ifdef.
|
||||
void PrintHandlingOptionalStaticInitializers(
|
||||
const FileDescriptor* file, io::Printer* printer,
|
||||
const char* with_static_init, const char* without_static_init,
|
||||
const char* var1 = NULL, const string& val1 = "",
|
||||
const char* var2 = NULL, const string& val2 = "");
|
||||
|
||||
void PrintHandlingOptionalStaticInitializers(
|
||||
const map<string, string>& vars, const FileDescriptor* file,
|
||||
io::Printer* printer, const char* with_static_init,
|
||||
const char* without_static_init);
|
||||
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,298 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_message_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
namespace {
|
||||
|
||||
void SetMessageVariables(const FieldDescriptor* descriptor,
|
||||
map<string, string>* variables,
|
||||
const Options& options) {
|
||||
SetCommonFieldVariables(descriptor, variables, options);
|
||||
(*variables)["type"] = FieldMessageTypeName(descriptor);
|
||||
(*variables)["stream_writer"] = (*variables)["declared_type"] +
|
||||
(HasFastArraySerialization(descriptor->message_type()->file()) ?
|
||||
"MaybeToArray" :
|
||||
"");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// ===================================================================
|
||||
|
||||
MessageFieldGenerator::
|
||||
MessageFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: descriptor_(descriptor) {
|
||||
SetMessageVariables(descriptor, &variables_, options);
|
||||
}
|
||||
|
||||
MessageFieldGenerator::~MessageFieldGenerator() {}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GeneratePrivateMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$type$* $name$_;\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
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");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"inline const $type$& $classname$::$name$() const {\n");
|
||||
|
||||
PrintHandlingOptionalStaticInitializers(
|
||||
variables_, descriptor_->file(), printer,
|
||||
// With static initializers.
|
||||
" return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n",
|
||||
// Without.
|
||||
" return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
|
||||
|
||||
printer->Print(variables_,
|
||||
"}\n"
|
||||
"inline $type$* $classname$::mutable_$name$() {\n"
|
||||
" set_has_$name$();\n"
|
||||
" if ($name$_ == NULL) $name$_ = new $type$;\n"
|
||||
" return $name$_;\n"
|
||||
"}\n"
|
||||
"inline $type$* $classname$::release_$name$() {\n"
|
||||
" clear_has_$name$();\n"
|
||||
" $type$* temp = $name$_;\n"
|
||||
" $name$_ = NULL;\n"
|
||||
" return temp;\n"
|
||||
"}\n"
|
||||
"inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
|
||||
" delete $name$_;\n"
|
||||
" $name$_ = $name$;\n"
|
||||
" if ($name$) {\n"
|
||||
" set_has_$name$();\n"
|
||||
" } else {\n"
|
||||
" clear_has_$name$();\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"if ($name$_ != NULL) $name$_->$type$::Clear();\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateMergingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_ = NULL;\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
|
||||
" input, mutable_$name$()));\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
|
||||
" $number$, input, mutable_$name$()));\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
|
||||
" $number$, this->$name$(), output);\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" Write$declared_type$NoVirtualToArray(\n"
|
||||
" $number$, this->$name$(), target);\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ +\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
|
||||
" this->$name$());\n");
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
RepeatedMessageFieldGenerator::
|
||||
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: descriptor_(descriptor) {
|
||||
SetMessageVariables(descriptor, &variables_, options);
|
||||
}
|
||||
|
||||
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GeneratePrivateMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n");
|
||||
}
|
||||
|
||||
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");
|
||||
printer->Print(variables_,
|
||||
"inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
|
||||
" $name$() const$deprecation$;\n"
|
||||
"inline ::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"
|
||||
" return $name$_.$cppget$(index);\n"
|
||||
"}\n"
|
||||
"inline $type$* $classname$::mutable_$name$(int index) {\n"
|
||||
" return $name$_.Mutable(index);\n"
|
||||
"}\n"
|
||||
"inline $type$* $classname$::add_$name$() {\n"
|
||||
" return $name$_.Add();\n"
|
||||
"}\n");
|
||||
printer->Print(variables_,
|
||||
"inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
|
||||
"$classname$::$name$() const {\n"
|
||||
" return $name$_;\n"
|
||||
"}\n"
|
||||
"inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
|
||||
"$classname$::mutable_$name$() {\n"
|
||||
" return &$name$_;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.Clear();\n");
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateMergingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
// Not needed for repeated fields.
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
|
||||
" input, add_$name$()));\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
|
||||
" $number$, input, add_$name$()));\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
|
||||
" $number$, this->$name$(i), output);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||
" target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" Write$declared_type$NoVirtualToArray(\n"
|
||||
" $number$, this->$name$(i), target);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ * this->$name$_size();\n"
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||
" total_size +=\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
|
||||
" this->$name$(i));\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -1,121 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
//
|
||||
// TODO(kenton): Share code with the versions of this test in other languages?
|
||||
// It seemed like parameterizing it would add more complexity than it is
|
||||
// worth.
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_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 cpp {
|
||||
namespace {
|
||||
|
||||
class TestGenerator : public CodeGenerator {
|
||||
public:
|
||||
TestGenerator() {}
|
||||
~TestGenerator() {}
|
||||
|
||||
virtual bool Generate(const FileDescriptor* file,
|
||||
const string& parameter,
|
||||
GeneratorContext* context,
|
||||
string* error) const {
|
||||
TryInsert("test.pb.h", "includes", context);
|
||||
TryInsert("test.pb.h", "namespace_scope", context);
|
||||
TryInsert("test.pb.h", "global_scope", context);
|
||||
TryInsert("test.pb.h", "class_scope:foo.Bar", context);
|
||||
TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", context);
|
||||
|
||||
TryInsert("test.pb.cc", "includes", context);
|
||||
TryInsert("test.pb.cc", "namespace_scope", context);
|
||||
TryInsert("test.pb.cc", "global_scope", context);
|
||||
return true;
|
||||
}
|
||||
|
||||
void TryInsert(const string& filename, const string& insertion_point,
|
||||
GeneratorContext* context) const {
|
||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
context->OpenForInsert(filename, insertion_point));
|
||||
io::Printer printer(output.get(), '$');
|
||||
printer.Print("// inserted $name$\n", "name", insertion_point);
|
||||
}
|
||||
};
|
||||
|
||||
// This test verifies that all the expected insertion points exist. It does
|
||||
// not verify that they are correctly-placed; that would require actually
|
||||
// compiling the output which is a bit more than I care to do for this test.
|
||||
TEST(CppPluginTest, PluginTest) {
|
||||
File::WriteStringToFileOrDie(
|
||||
"syntax = \"proto2\";\n"
|
||||
"package foo;\n"
|
||||
"message Bar {\n"
|
||||
" message Baz {}\n"
|
||||
"}\n",
|
||||
TestTempDir() + "/test.proto");
|
||||
|
||||
google::protobuf::compiler::CommandLineInterface cli;
|
||||
cli.SetInputsAreProtoPathRelative(true);
|
||||
|
||||
CppGenerator cpp_generator;
|
||||
TestGenerator test_generator;
|
||||
cli.RegisterGenerator("--cpp_out", &cpp_generator, "");
|
||||
cli.RegisterGenerator("--test_out", &test_generator, "");
|
||||
|
||||
string proto_path = "-I" + TestTempDir();
|
||||
string cpp_out = "--cpp_out=" + TestTempDir();
|
||||
string test_out = "--test_out=" + TestTempDir();
|
||||
|
||||
const char* argv[] = {
|
||||
"protoc",
|
||||
proto_path.c_str(),
|
||||
cpp_out.c_str(),
|
||||
test_out.c_str(),
|
||||
"test.proto"
|
||||
};
|
||||
|
||||
EXPECT_EQ(0, cli.Run(5, argv));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -1,491 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_string_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_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 cpp {
|
||||
|
||||
namespace {
|
||||
|
||||
void SetStringVariables(const FieldDescriptor* descriptor,
|
||||
map<string, string>* variables,
|
||||
const Options& options) {
|
||||
SetCommonFieldVariables(descriptor, variables, options);
|
||||
(*variables)["default"] = DefaultValue(descriptor);
|
||||
(*variables)["default_length"] =
|
||||
SimpleItoa(descriptor->default_value_string().length());
|
||||
(*variables)["default_variable"] = descriptor->default_value_string().empty()
|
||||
? "&::google::protobuf::internal::kEmptyString"
|
||||
: "_default_" + FieldName(descriptor) + "_";
|
||||
(*variables)["pointer_type"] =
|
||||
descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// ===================================================================
|
||||
|
||||
StringFieldGenerator::
|
||||
StringFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: descriptor_(descriptor) {
|
||||
SetStringVariables(descriptor, &variables_, options);
|
||||
}
|
||||
|
||||
StringFieldGenerator::~StringFieldGenerator() {}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GeneratePrivateMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_, "::std::string* $name$_;\n");
|
||||
if (!descriptor_->default_value_string().empty()) {
|
||||
printer->Print(variables_, "static ::std::string* $default_variable$;\n");
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
// If we're using StringFieldGenerator for a field with a ctype, it's
|
||||
// because that ctype isn't actually implemented. In particular, this is
|
||||
// true of ctype=CORD and ctype=STRING_PIECE in the open source release.
|
||||
// We aren't releasing Cord because it has too many Google-specific
|
||||
// dependencies and we aren't releasing StringPiece because it's hardly
|
||||
// useful outside of Google and because it would get confusing to have
|
||||
// multiple instances of the StringPiece class in different libraries (PCRE
|
||||
// already includes it for their C++ bindings, which came from Google).
|
||||
//
|
||||
// In any case, we make all the accessors private while still actually
|
||||
// using a string to represent the field internally. This way, we can
|
||||
// guarantee that if we do ever implement the ctype, it won't break any
|
||||
// existing users who might be -- for whatever reason -- already using .proto
|
||||
// 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) {
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
" private:\n"
|
||||
" // Hidden due to unknown ctype option.\n");
|
||||
printer->Indent();
|
||||
}
|
||||
|
||||
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)"
|
||||
"$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");
|
||||
|
||||
|
||||
if (descriptor_->options().ctype() != FieldOptions::STRING) {
|
||||
printer->Outdent();
|
||||
printer->Print(" public:\n");
|
||||
printer->Indent();
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"inline const ::std::string& $classname$::$name$() const {\n"
|
||||
" return *$name$_;\n"
|
||||
"}\n"
|
||||
"inline void $classname$::set_$name$(const ::std::string& value) {\n"
|
||||
" set_has_$name$();\n"
|
||||
" if ($name$_ == $default_variable$) {\n"
|
||||
" $name$_ = new ::std::string;\n"
|
||||
" }\n"
|
||||
" $name$_->assign(value);\n"
|
||||
"}\n"
|
||||
"inline void $classname$::set_$name$(const char* value) {\n"
|
||||
" set_has_$name$();\n"
|
||||
" if ($name$_ == $default_variable$) {\n"
|
||||
" $name$_ = new ::std::string;\n"
|
||||
" }\n"
|
||||
" $name$_->assign(value);\n"
|
||||
"}\n"
|
||||
"inline "
|
||||
"void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
|
||||
" set_has_$name$();\n"
|
||||
" if ($name$_ == $default_variable$) {\n"
|
||||
" $name$_ = new ::std::string;\n"
|
||||
" }\n"
|
||||
" $name$_->assign(reinterpret_cast<const char*>(value), size);\n"
|
||||
"}\n"
|
||||
"inline ::std::string* $classname$::mutable_$name$() {\n"
|
||||
" set_has_$name$();\n"
|
||||
" if ($name$_ == $default_variable$) {\n");
|
||||
if (descriptor_->default_value_string().empty()) {
|
||||
printer->Print(variables_,
|
||||
" $name$_ = new ::std::string;\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" $name$_ = new ::std::string(*$default_variable$);\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" }\n"
|
||||
" return $name$_;\n"
|
||||
"}\n"
|
||||
"inline ::std::string* $classname$::release_$name$() {\n"
|
||||
" clear_has_$name$();\n"
|
||||
" if ($name$_ == $default_variable$) {\n"
|
||||
" return NULL;\n"
|
||||
" } else {\n"
|
||||
" ::std::string* temp = $name$_;\n"
|
||||
" $name$_ = const_cast< ::std::string*>($default_variable$);\n"
|
||||
" return temp;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
|
||||
" if ($name$_ != $default_variable$) {\n"
|
||||
" delete $name$_;\n"
|
||||
" }\n"
|
||||
" if ($name$) {\n"
|
||||
" set_has_$name$();\n"
|
||||
" $name$_ = $name$;\n"
|
||||
" } else {\n"
|
||||
" clear_has_$name$();\n"
|
||||
" $name$_ = const_cast< ::std::string*>($default_variable$);\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
if (!descriptor_->default_value_string().empty()) {
|
||||
// Initialized in GenerateDefaultInstanceAllocator.
|
||||
printer->Print(variables_,
|
||||
"::std::string* $classname$::$default_variable$ = NULL;\n");
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
if (descriptor_->default_value_string().empty()) {
|
||||
printer->Print(variables_,
|
||||
"if ($name$_ != $default_variable$) {\n"
|
||||
" $name$_->clear();\n"
|
||||
"}\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"if ($name$_ != $default_variable$) {\n"
|
||||
" $name$_->assign(*$default_variable$);\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateMergingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "set_$name$(from.$name$());\n");
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"$name$_ = const_cast< ::std::string*>($default_variable$);\n");
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateDestructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"if ($name$_ != $default_variable$) {\n"
|
||||
" delete $name$_;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateDefaultInstanceAllocator(io::Printer* printer) const {
|
||||
if (!descriptor_->default_value_string().empty()) {
|
||||
printer->Print(variables_,
|
||||
"$classname$::$default_variable$ =\n"
|
||||
" new ::std::string($default$, $default_length$);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateShutdownCode(io::Printer* printer) const {
|
||||
if (!descriptor_->default_value_string().empty()) {
|
||||
printer->Print(variables_,
|
||||
"delete $classname$::$default_variable$;\n");
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
|
||||
" input, this->mutable_$name$()));\n");
|
||||
if (HasUtf8Verification(descriptor_->file()) &&
|
||||
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
||||
" this->$name$().data(), this->$name$().length(),\n"
|
||||
" ::google::protobuf::internal::WireFormat::PARSE);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
if (HasUtf8Verification(descriptor_->file()) &&
|
||||
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
||||
" this->$name$().data(), this->$name$().length(),\n"
|
||||
" ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
|
||||
" $number$, this->$name$(), output);\n");
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
if (HasUtf8Verification(descriptor_->file()) &&
|
||||
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
||||
" this->$name$().data(), this->$name$().length(),\n"
|
||||
" ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"target =\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(\n"
|
||||
" $number$, this->$name$(), target);\n");
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ +\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
|
||||
" this->$name$());\n");
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
RepeatedStringFieldGenerator::
|
||||
RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: descriptor_(descriptor) {
|
||||
SetStringVariables(descriptor, &variables_, options);
|
||||
}
|
||||
|
||||
RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GeneratePrivateMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::RepeatedPtrField< ::std::string> $name$_;\n");
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
// See comment above about unknown ctypes.
|
||||
if (descriptor_->options().ctype() != FieldOptions::STRING) {
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
" private:\n"
|
||||
" // Hidden due to unknown ctype option.\n");
|
||||
printer->Indent();
|
||||
}
|
||||
|
||||
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 "
|
||||
"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)"
|
||||
"$deprecation$;\n");
|
||||
|
||||
printer->Print(variables_,
|
||||
"inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const"
|
||||
"$deprecation$;\n"
|
||||
"inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
|
||||
"$deprecation$;\n");
|
||||
|
||||
if (descriptor_->options().ctype() != FieldOptions::STRING) {
|
||||
printer->Outdent();
|
||||
printer->Print(" public:\n");
|
||||
printer->Indent();
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"inline const ::std::string& $classname$::$name$(int index) const {\n"
|
||||
" return $name$_.$cppget$(index);\n"
|
||||
"}\n"
|
||||
"inline ::std::string* $classname$::mutable_$name$(int index) {\n"
|
||||
" return $name$_.Mutable(index);\n"
|
||||
"}\n"
|
||||
"inline void $classname$::set_$name$(int index, const ::std::string& value) {\n"
|
||||
" $name$_.Mutable(index)->assign(value);\n"
|
||||
"}\n"
|
||||
"inline void $classname$::set_$name$(int index, const char* value) {\n"
|
||||
" $name$_.Mutable(index)->assign(value);\n"
|
||||
"}\n"
|
||||
"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"
|
||||
"}\n"
|
||||
"inline ::std::string* $classname$::add_$name$() {\n"
|
||||
" return $name$_.Add();\n"
|
||||
"}\n"
|
||||
"inline void $classname$::add_$name$(const ::std::string& value) {\n"
|
||||
" $name$_.Add()->assign(value);\n"
|
||||
"}\n"
|
||||
"inline void $classname$::add_$name$(const char* value) {\n"
|
||||
" $name$_.Add()->assign(value);\n"
|
||||
"}\n"
|
||||
"inline void "
|
||||
"$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
|
||||
" $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
|
||||
"}\n");
|
||||
printer->Print(variables_,
|
||||
"inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
|
||||
"$classname$::$name$() const {\n"
|
||||
" return $name$_;\n"
|
||||
"}\n"
|
||||
"inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
|
||||
"$classname$::mutable_$name$() {\n"
|
||||
" return &$name$_;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.Clear();\n");
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateMergingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
// Not needed for repeated fields.
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
|
||||
" input, this->add_$name$()));\n");
|
||||
if (HasUtf8Verification(descriptor_->file()) &&
|
||||
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
||||
" this->$name$(this->$name$_size() - 1).data(),\n"
|
||||
" this->$name$(this->$name$_size() - 1).length(),\n"
|
||||
" ::google::protobuf::internal::WireFormat::PARSE);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||
if (HasUtf8Verification(descriptor_->file()) &&
|
||||
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
||||
" this->$name$(i).data(), this->$name$(i).length(),\n"
|
||||
" ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
|
||||
" $number$, this->$name$(i), output);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||
if (HasUtf8Verification(descriptor_->file()) &&
|
||||
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
||||
" this->$name$(i).data(), this->$name$(i).length(),\n"
|
||||
" ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" Write$declared_type$ToArray($number$, this->$name$(i), target);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ * this->$name$_size();\n"
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||
" total_size += ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
|
||||
" this->$name$(i));\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -1,603 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/compiler/java/java_enum_field.h>
|
||||
#include <google/protobuf/compiler/java/java_doc_comment.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/compiler/java/java_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 java {
|
||||
|
||||
namespace {
|
||||
|
||||
// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
|
||||
// repeat code between this and the other field types.
|
||||
void SetEnumVariables(const FieldDescriptor* descriptor,
|
||||
int messageBitIndex,
|
||||
int builderBitIndex,
|
||||
map<string, string>* variables) {
|
||||
(*variables)["name"] =
|
||||
UnderscoresToCamelCase(descriptor);
|
||||
(*variables)["capitalized_name"] =
|
||||
UnderscoresToCapitalizedCamelCase(descriptor);
|
||||
(*variables)["constant_name"] = FieldConstantName(descriptor);
|
||||
(*variables)["number"] = SimpleItoa(descriptor->number());
|
||||
(*variables)["type"] = ClassName(descriptor->enum_type());
|
||||
(*variables)["default"] = DefaultValue(descriptor);
|
||||
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
|
||||
(*variables)["tag_size"] = SimpleItoa(
|
||||
internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
|
||||
// TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
|
||||
// by the proto compiler
|
||||
(*variables)["deprecation"] = descriptor->options().deprecated()
|
||||
? "@java.lang.Deprecated " : "";
|
||||
(*variables)["on_changed"] =
|
||||
HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
|
||||
|
||||
// For singular messages and builders, one bit is used for the hasField bit.
|
||||
(*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
|
||||
(*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
|
||||
|
||||
(*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
|
||||
(*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
|
||||
(*variables)["clear_has_field_bit_builder"] =
|
||||
GenerateClearBit(builderBitIndex);
|
||||
|
||||
// For repated builders, one bit is used for whether the array is immutable.
|
||||
(*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
|
||||
(*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
|
||||
(*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
|
||||
|
||||
// For repeated fields, one bit is used for whether the array is immutable
|
||||
// in the parsing constructor.
|
||||
(*variables)["get_mutable_bit_parser"] =
|
||||
GenerateGetBitMutableLocal(builderBitIndex);
|
||||
(*variables)["set_mutable_bit_parser"] =
|
||||
GenerateSetBitMutableLocal(builderBitIndex);
|
||||
|
||||
(*variables)["get_has_field_bit_from_local"] =
|
||||
GenerateGetBitFromLocal(builderBitIndex);
|
||||
(*variables)["set_has_field_bit_to_local"] =
|
||||
GenerateSetBitToLocal(messageBitIndex);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// ===================================================================
|
||||
|
||||
EnumFieldGenerator::
|
||||
EnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||
int messageBitIndex,
|
||||
int builderBitIndex)
|
||||
: descriptor_(descriptor), messageBitIndex_(messageBitIndex),
|
||||
builderBitIndex_(builderBitIndex) {
|
||||
SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_);
|
||||
}
|
||||
|
||||
EnumFieldGenerator::~EnumFieldGenerator() {}
|
||||
|
||||
int EnumFieldGenerator::GetNumBitsForMessage() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EnumFieldGenerator::GetNumBitsForBuilder() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateInterfaceMembers(io::Printer* printer) const {
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$boolean has$capitalized_name$();\n");
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$$type$ get$capitalized_name$();\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"private $type$ $name$_;\n");
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$public boolean has$capitalized_name$() {\n"
|
||||
" return $get_has_field_bit_message$;\n"
|
||||
"}\n");
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$public $type$ get$capitalized_name$() {\n"
|
||||
" return $name$_;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateBuilderMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"private $type$ $name$_ = $default$;\n");
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$public boolean has$capitalized_name$() {\n"
|
||||
" return $get_has_field_bit_builder$;\n"
|
||||
"}\n");
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$public $type$ get$capitalized_name$() {\n"
|
||||
" return $name$_;\n"
|
||||
"}\n");
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
|
||||
" if (value == null) {\n"
|
||||
" throw new NullPointerException();\n"
|
||||
" }\n"
|
||||
" $set_has_field_bit_builder$;\n"
|
||||
" $name$_ = value;\n"
|
||||
" $on_changed$\n"
|
||||
" return this;\n"
|
||||
"}\n");
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$public Builder clear$capitalized_name$() {\n"
|
||||
" $clear_has_field_bit_builder$;\n"
|
||||
" $name$_ = $default$;\n"
|
||||
" $on_changed$\n"
|
||||
" return this;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
|
||||
// noop for enums
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateInitializationCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_ = $default$;\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateBuilderClearCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"$name$_ = $default$;\n"
|
||||
"$clear_has_field_bit_builder$;\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateMergingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"if (other.has$capitalized_name$()) {\n"
|
||||
" set$capitalized_name$(other.get$capitalized_name$());\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateBuildingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"if ($get_has_field_bit_from_local$) {\n"
|
||||
" $set_has_field_bit_to_local$;\n"
|
||||
"}\n"
|
||||
"result.$name$_ = $name$_;\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateParsingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"int rawValue = input.readEnum();\n"
|
||||
"$type$ value = $type$.valueOf(rawValue);\n");
|
||||
if (HasUnknownFields(descriptor_->containing_type())) {
|
||||
printer->Print(variables_,
|
||||
"if (value == null) {\n"
|
||||
" unknownFields.mergeVarintField($number$, rawValue);\n"
|
||||
"} else {\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"if (value != null) {\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" $set_has_field_bit_message$;\n"
|
||||
" $name$_ = value;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateParsingDoneCode(io::Printer* printer) const {
|
||||
// noop for enums
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateSerializationCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"if ($get_has_field_bit_message$) {\n"
|
||||
" output.writeEnum($number$, $name$_.getNumber());\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateSerializedSizeCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"if ($get_has_field_bit_message$) {\n"
|
||||
" size += com.google.protobuf.CodedOutputStream\n"
|
||||
" .computeEnumSize($number$, $name$_.getNumber());\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateEqualsCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"result = result &&\n"
|
||||
" (get$capitalized_name$() == other.get$capitalized_name$());\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateHashCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"hash = (37 * hash) + $constant_name$;\n"
|
||||
"hash = (53 * hash) + hashEnum(get$capitalized_name$());\n");
|
||||
}
|
||||
|
||||
string EnumFieldGenerator::GetBoxedType() const {
|
||||
return ClassName(descriptor_->enum_type());
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
RepeatedEnumFieldGenerator::
|
||||
RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||
int messageBitIndex,
|
||||
int builderBitIndex)
|
||||
: descriptor_(descriptor), messageBitIndex_(messageBitIndex),
|
||||
builderBitIndex_(builderBitIndex) {
|
||||
SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_);
|
||||
}
|
||||
|
||||
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
|
||||
|
||||
int RepeatedEnumFieldGenerator::GetNumBitsForMessage() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RepeatedEnumFieldGenerator::GetNumBitsForBuilder() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateInterfaceMembers(io::Printer* printer) const {
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$java.util.List<$type$> get$capitalized_name$List();\n");
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$int get$capitalized_name$Count();\n");
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$$type$ get$capitalized_name$(int index);\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"private java.util.List<$type$> $name$_;\n");
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
|
||||
" return $name$_;\n" // note: unmodifiable list
|
||||
"}\n");
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$public int get$capitalized_name$Count() {\n"
|
||||
" return $name$_.size();\n"
|
||||
"}\n");
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$public $type$ get$capitalized_name$(int index) {\n"
|
||||
" return $name$_.get(index);\n"
|
||||
"}\n");
|
||||
|
||||
if (descriptor_->options().packed() &&
|
||||
HasGeneratedMethods(descriptor_->containing_type())) {
|
||||
printer->Print(variables_,
|
||||
"private int $name$MemoizedSerializedSize;\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateBuilderMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
// One field is the list and the other field keeps track of whether the
|
||||
// list is immutable. If it's immutable, the invariant is that it must
|
||||
// either an instance of Collections.emptyList() or it's an ArrayList
|
||||
// wrapped in a Collections.unmodifiableList() wrapper and nobody else has
|
||||
// a refererence to the underlying ArrayList. This invariant allows us to
|
||||
// share instances of lists between protocol buffers avoiding expensive
|
||||
// memory allocations. Note, immutable is a strong guarantee here -- not
|
||||
// just that the list cannot be modified via the reference but that the
|
||||
// list can never be modified.
|
||||
"private java.util.List<$type$> $name$_ =\n"
|
||||
" java.util.Collections.emptyList();\n"
|
||||
|
||||
"private void ensure$capitalized_name$IsMutable() {\n"
|
||||
" if (!$get_mutable_bit_builder$) {\n"
|
||||
" $name$_ = new java.util.ArrayList<$type$>($name$_);\n"
|
||||
" $set_mutable_bit_builder$;\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
// Note: We return an unmodifiable list because otherwise the caller
|
||||
// could hold on to the returned list and modify it after the message
|
||||
// has been built, thus mutating the message which is supposed to be
|
||||
// immutable.
|
||||
"$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
|
||||
" return java.util.Collections.unmodifiableList($name$_);\n"
|
||||
"}\n");
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$public int get$capitalized_name$Count() {\n"
|
||||
" return $name$_.size();\n"
|
||||
"}\n");
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$public $type$ get$capitalized_name$(int index) {\n"
|
||||
" return $name$_.get(index);\n"
|
||||
"}\n");
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$public Builder set$capitalized_name$(\n"
|
||||
" int index, $type$ value) {\n"
|
||||
" if (value == null) {\n"
|
||||
" throw new NullPointerException();\n"
|
||||
" }\n"
|
||||
" ensure$capitalized_name$IsMutable();\n"
|
||||
" $name$_.set(index, value);\n"
|
||||
" $on_changed$\n"
|
||||
" return this;\n"
|
||||
"}\n");
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
|
||||
" if (value == null) {\n"
|
||||
" throw new NullPointerException();\n"
|
||||
" }\n"
|
||||
" ensure$capitalized_name$IsMutable();\n"
|
||||
" $name$_.add(value);\n"
|
||||
" $on_changed$\n"
|
||||
" return this;\n"
|
||||
"}\n");
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$public Builder addAll$capitalized_name$(\n"
|
||||
" java.lang.Iterable<? extends $type$> values) {\n"
|
||||
" ensure$capitalized_name$IsMutable();\n"
|
||||
" super.addAll(values, $name$_);\n"
|
||||
" $on_changed$\n"
|
||||
" return this;\n"
|
||||
"}\n");
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecation$public Builder clear$capitalized_name$() {\n"
|
||||
" $name$_ = java.util.Collections.emptyList();\n"
|
||||
" $clear_mutable_bit_builder$;\n"
|
||||
" $on_changed$\n"
|
||||
" return this;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
|
||||
// noop for enums
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateInitializationCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateBuilderClearCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"$name$_ = java.util.Collections.emptyList();\n"
|
||||
"$clear_mutable_bit_builder$;\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateMergingCode(io::Printer* printer) const {
|
||||
// The code below does two optimizations:
|
||||
// 1. If the other list is empty, there's nothing to do. This ensures we
|
||||
// don't allocate a new array if we already have an immutable one.
|
||||
// 2. If the other list is non-empty and our current list is empty, we can
|
||||
// reuse the other list which is guaranteed to be immutable.
|
||||
printer->Print(variables_,
|
||||
"if (!other.$name$_.isEmpty()) {\n"
|
||||
" if ($name$_.isEmpty()) {\n"
|
||||
" $name$_ = other.$name$_;\n"
|
||||
" $clear_mutable_bit_builder$;\n"
|
||||
" } else {\n"
|
||||
" ensure$capitalized_name$IsMutable();\n"
|
||||
" $name$_.addAll(other.$name$_);\n"
|
||||
" }\n"
|
||||
" $on_changed$\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateBuildingCode(io::Printer* printer) const {
|
||||
// The code below ensures that the result has an immutable list. If our
|
||||
// list is immutable, we can just reuse it. If not, we make it immutable.
|
||||
printer->Print(variables_,
|
||||
"if ($get_mutable_bit_builder$) {\n"
|
||||
" $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
|
||||
" $clear_mutable_bit_builder$;\n"
|
||||
"}\n"
|
||||
"result.$name$_ = $name$_;\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateParsingCode(io::Printer* printer) const {
|
||||
// Read and store the enum
|
||||
printer->Print(variables_,
|
||||
"int rawValue = input.readEnum();\n"
|
||||
"$type$ value = $type$.valueOf(rawValue);\n");
|
||||
if (HasUnknownFields(descriptor_->containing_type())) {
|
||||
printer->Print(variables_,
|
||||
"if (value == null) {\n"
|
||||
" unknownFields.mergeVarintField($number$, rawValue);\n"
|
||||
"} else {\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"if (value != null) {\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" if (!$get_mutable_bit_parser$) {\n"
|
||||
" $name$_ = new java.util.ArrayList<$type$>();\n"
|
||||
" $set_mutable_bit_parser$;\n"
|
||||
" }\n"
|
||||
" $name$_.add(value);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateParsingCodeFromPacked(io::Printer* printer) const {
|
||||
// Wrap GenerateParsingCode's contents with a while loop.
|
||||
|
||||
printer->Print(variables_,
|
||||
"int length = input.readRawVarint32();\n"
|
||||
"int oldLimit = input.pushLimit(length);\n"
|
||||
"while(input.getBytesUntilLimit() > 0) {\n");
|
||||
printer->Indent();
|
||||
|
||||
GenerateParsingCode(printer);
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(variables_,
|
||||
"}\n"
|
||||
"input.popLimit(oldLimit);\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateParsingDoneCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"if ($get_mutable_bit_parser$) {\n"
|
||||
" $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateSerializationCode(io::Printer* printer) const {
|
||||
if (descriptor_->options().packed()) {
|
||||
printer->Print(variables_,
|
||||
"if (get$capitalized_name$List().size() > 0) {\n"
|
||||
" output.writeRawVarint32($tag$);\n"
|
||||
" output.writeRawVarint32($name$MemoizedSerializedSize);\n"
|
||||
"}\n"
|
||||
"for (int i = 0; i < $name$_.size(); i++) {\n"
|
||||
" output.writeEnumNoTag($name$_.get(i).getNumber());\n"
|
||||
"}\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < $name$_.size(); i++) {\n"
|
||||
" output.writeEnum($number$, $name$_.get(i).getNumber());\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateSerializedSizeCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"{\n"
|
||||
" int dataSize = 0;\n");
|
||||
printer->Indent();
|
||||
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < $name$_.size(); i++) {\n"
|
||||
" dataSize += com.google.protobuf.CodedOutputStream\n"
|
||||
" .computeEnumSizeNoTag($name$_.get(i).getNumber());\n"
|
||||
"}\n");
|
||||
printer->Print(
|
||||
"size += dataSize;\n");
|
||||
if (descriptor_->options().packed()) {
|
||||
printer->Print(variables_,
|
||||
"if (!get$capitalized_name$List().isEmpty()) {"
|
||||
" size += $tag_size$;\n"
|
||||
" size += com.google.protobuf.CodedOutputStream\n"
|
||||
" .computeRawVarint32Size(dataSize);\n"
|
||||
"}");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"size += $tag_size$ * $name$_.size();\n");
|
||||
}
|
||||
|
||||
// cache the data size for packed fields.
|
||||
if (descriptor_->options().packed()) {
|
||||
printer->Print(variables_,
|
||||
"$name$MemoizedSerializedSize = dataSize;\n");
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateEqualsCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"result = result && get$capitalized_name$List()\n"
|
||||
" .equals(other.get$capitalized_name$List());\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateHashCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"if (get$capitalized_name$Count() > 0) {\n"
|
||||
" hash = (37 * hash) + $constant_name$;\n"
|
||||
" hash = (53 * hash) + hashEnumList(get$capitalized_name$List());\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
string RepeatedEnumFieldGenerator::GetBoxedType() const {
|
||||
return ClassName(descriptor_->enum_type());
|
||||
}
|
||||
|
||||
} // namespace java
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -1,218 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/compiler/java/java_extension.h>
|
||||
#include <google/protobuf/compiler/java/java_doc_comment.h>
|
||||
#include <google/protobuf/compiler/java/java_helpers.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace java {
|
||||
|
||||
namespace {
|
||||
|
||||
const char* TypeName(FieldDescriptor::Type field_type) {
|
||||
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 "BYTES";
|
||||
case FieldDescriptor::TYPE_ENUM : return "ENUM";
|
||||
case FieldDescriptor::TYPE_GROUP : return "GROUP";
|
||||
case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE";
|
||||
|
||||
// No default because we want the compiler to complain if any new
|
||||
// types are added.
|
||||
}
|
||||
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor)
|
||||
: descriptor_(descriptor) {
|
||||
if (descriptor_->extension_scope() != NULL) {
|
||||
scope_ = ClassName(descriptor_->extension_scope());
|
||||
} else {
|
||||
scope_ = ClassName(descriptor_->file());
|
||||
}
|
||||
}
|
||||
|
||||
ExtensionGenerator::~ExtensionGenerator() {}
|
||||
|
||||
// Initializes the vars referenced in the generated code templates.
|
||||
void InitTemplateVars(const FieldDescriptor* descriptor,
|
||||
const string& scope,
|
||||
map<string, string>* vars_pointer) {
|
||||
map<string, string> &vars = *vars_pointer;
|
||||
vars["scope"] = scope;
|
||||
vars["name"] = UnderscoresToCamelCase(descriptor);
|
||||
vars["containing_type"] = ClassName(descriptor->containing_type());
|
||||
vars["number"] = SimpleItoa(descriptor->number());
|
||||
vars["constant_name"] = FieldConstantName(descriptor);
|
||||
vars["index"] = SimpleItoa(descriptor->index());
|
||||
vars["default"] =
|
||||
descriptor->is_repeated() ? "" : DefaultValue(descriptor);
|
||||
vars["type_constant"] = TypeName(GetType(descriptor));
|
||||
vars["packed"] = descriptor->options().packed() ? "true" : "false";
|
||||
vars["enum_map"] = "null";
|
||||
vars["prototype"] = "null";
|
||||
|
||||
JavaType java_type = GetJavaType(descriptor);
|
||||
string singular_type;
|
||||
switch (java_type) {
|
||||
case JAVATYPE_MESSAGE:
|
||||
singular_type = ClassName(descriptor->message_type());
|
||||
vars["prototype"] = singular_type + ".getDefaultInstance()";
|
||||
break;
|
||||
case JAVATYPE_ENUM:
|
||||
singular_type = ClassName(descriptor->enum_type());
|
||||
vars["enum_map"] = singular_type + ".internalGetValueMap()";
|
||||
break;
|
||||
default:
|
||||
singular_type = BoxedPrimitiveTypeName(java_type);
|
||||
break;
|
||||
}
|
||||
vars["type"] = descriptor->is_repeated() ?
|
||||
"java.util.List<" + singular_type + ">" : singular_type;
|
||||
vars["singular_type"] = singular_type;
|
||||
}
|
||||
|
||||
void ExtensionGenerator::Generate(io::Printer* printer) {
|
||||
map<string, string> vars;
|
||||
InitTemplateVars(descriptor_, scope_, &vars);
|
||||
printer->Print(vars,
|
||||
"public static final int $constant_name$ = $number$;\n");
|
||||
|
||||
WriteFieldDocComment(printer, descriptor_);
|
||||
if (HasDescriptorMethods(descriptor_->file())) {
|
||||
// Non-lite extensions
|
||||
if (descriptor_->extension_scope() == NULL) {
|
||||
// Non-nested
|
||||
printer->Print(
|
||||
vars,
|
||||
"public static final\n"
|
||||
" com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
|
||||
" $containing_type$,\n"
|
||||
" $type$> $name$ = com.google.protobuf.GeneratedMessage\n"
|
||||
" .newFileScopedGeneratedExtension(\n"
|
||||
" $singular_type$.class,\n"
|
||||
" $prototype$);\n");
|
||||
} else {
|
||||
// Nested
|
||||
printer->Print(
|
||||
vars,
|
||||
"public static final\n"
|
||||
" com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
|
||||
" $containing_type$,\n"
|
||||
" $type$> $name$ = com.google.protobuf.GeneratedMessage\n"
|
||||
" .newMessageScopedGeneratedExtension(\n"
|
||||
" $scope$.getDefaultInstance(),\n"
|
||||
" $index$,\n"
|
||||
" $singular_type$.class,\n"
|
||||
" $prototype$);\n");
|
||||
}
|
||||
} else {
|
||||
// Lite extensions
|
||||
if (descriptor_->is_repeated()) {
|
||||
printer->Print(
|
||||
vars,
|
||||
"public static final\n"
|
||||
" com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n"
|
||||
" $containing_type$,\n"
|
||||
" $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n"
|
||||
" .newRepeatedGeneratedExtension(\n"
|
||||
" $containing_type$.getDefaultInstance(),\n"
|
||||
" $prototype$,\n"
|
||||
" $enum_map$,\n"
|
||||
" $number$,\n"
|
||||
" com.google.protobuf.WireFormat.FieldType.$type_constant$,\n"
|
||||
" $packed$);\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
vars,
|
||||
"public static final\n"
|
||||
" com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n"
|
||||
" $containing_type$,\n"
|
||||
" $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n"
|
||||
" .newSingularGeneratedExtension(\n"
|
||||
" $containing_type$.getDefaultInstance(),\n"
|
||||
" $default$,\n"
|
||||
" $prototype$,\n"
|
||||
" $enum_map$,\n"
|
||||
" $number$,\n"
|
||||
" com.google.protobuf.WireFormat.FieldType.$type_constant$);\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExtensionGenerator::GenerateNonNestedInitializationCode(
|
||||
io::Printer* printer) {
|
||||
if (descriptor_->extension_scope() == NULL &&
|
||||
HasDescriptorMethods(descriptor_->file())) {
|
||||
// Only applies to non-nested, non-lite extensions.
|
||||
printer->Print(
|
||||
"$name$.internalInit(descriptor.getExtensions().get($index$));\n",
|
||||
"name", UnderscoresToCamelCase(descriptor_),
|
||||
"index", SimpleItoa(descriptor_->index()));
|
||||
}
|
||||
}
|
||||
|
||||
void ExtensionGenerator::GenerateRegistrationCode(io::Printer* printer) {
|
||||
printer->Print(
|
||||
"registry.add($scope$.$name$);\n",
|
||||
"scope", scope_,
|
||||
"name", UnderscoresToCamelCase(descriptor_));
|
||||
}
|
||||
|
||||
} // namespace java
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -1,137 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/compiler/java/java_field.h>
|
||||
#include <google/protobuf/compiler/java/java_helpers.h>
|
||||
#include <google/protobuf/compiler/java/java_primitive_field.h>
|
||||
#include <google/protobuf/compiler/java/java_enum_field.h>
|
||||
#include <google/protobuf/compiler/java/java_message_field.h>
|
||||
#include <google/protobuf/compiler/java/java_string_field.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace java {
|
||||
|
||||
FieldGenerator::~FieldGenerator() {}
|
||||
|
||||
void FieldGenerator::GenerateParsingCodeFromPacked(io::Printer* printer) const {
|
||||
// Reaching here indicates a bug. Cases are:
|
||||
// - This FieldGenerator should support packing, but this method should be
|
||||
// overridden.
|
||||
// - This FieldGenerator doesn't support packing, and this method should
|
||||
// never have been called.
|
||||
GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() "
|
||||
<< "called on field generator that does not support packing.";
|
||||
}
|
||||
|
||||
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 and assign them bit indices for their
|
||||
// bit fields.
|
||||
int messageBitIndex = 0;
|
||||
int builderBitIndex = 0;
|
||||
for (int i = 0; i < descriptor->field_count(); i++) {
|
||||
FieldGenerator* generator = MakeGenerator(descriptor->field(i),
|
||||
messageBitIndex, builderBitIndex);
|
||||
field_generators_[i].reset(generator);
|
||||
messageBitIndex += generator->GetNumBitsForMessage();
|
||||
builderBitIndex += generator->GetNumBitsForBuilder();
|
||||
}
|
||||
for (int i = 0; i < descriptor->extension_count(); i++) {
|
||||
FieldGenerator* generator = MakeGenerator(descriptor->extension(i),
|
||||
messageBitIndex, builderBitIndex);
|
||||
extension_generators_[i].reset(generator);
|
||||
messageBitIndex += generator->GetNumBitsForMessage();
|
||||
builderBitIndex += generator->GetNumBitsForBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
FieldGenerator* FieldGeneratorMap::MakeGenerator(
|
||||
const FieldDescriptor* field, int messageBitIndex, int builderBitIndex) {
|
||||
if (field->is_repeated()) {
|
||||
switch (GetJavaType(field)) {
|
||||
case JAVATYPE_MESSAGE:
|
||||
return new RepeatedMessageFieldGenerator(
|
||||
field, messageBitIndex, builderBitIndex);
|
||||
case JAVATYPE_ENUM:
|
||||
return new RepeatedEnumFieldGenerator(
|
||||
field, messageBitIndex, builderBitIndex);
|
||||
case JAVATYPE_STRING:
|
||||
return new RepeatedStringFieldGenerator(
|
||||
field, messageBitIndex, builderBitIndex);
|
||||
default:
|
||||
return new RepeatedPrimitiveFieldGenerator(
|
||||
field, messageBitIndex, builderBitIndex);
|
||||
}
|
||||
} else {
|
||||
switch (GetJavaType(field)) {
|
||||
case JAVATYPE_MESSAGE:
|
||||
return new MessageFieldGenerator(
|
||||
field, messageBitIndex, builderBitIndex);
|
||||
case JAVATYPE_ENUM:
|
||||
return new EnumFieldGenerator(
|
||||
field, messageBitIndex, builderBitIndex);
|
||||
case JAVATYPE_STRING:
|
||||
return new StringFieldGenerator(
|
||||
field, messageBitIndex, builderBitIndex);
|
||||
default:
|
||||
return new PrimitiveFieldGenerator(
|
||||
field, messageBitIndex, builderBitIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
} // namespace java
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -1,490 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/compiler/java/java_file.h>
|
||||
#include <google/protobuf/compiler/java/java_enum.h>
|
||||
#include <google/protobuf/compiler/java/java_service.h>
|
||||
#include <google/protobuf/compiler/java/java_extension.h>
|
||||
#include <google/protobuf/compiler/java/java_helpers.h>
|
||||
#include <google/protobuf/compiler/java/java_message.h>
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/dynamic_message.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace java {
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
// Recursively searches the given message to collect extensions.
|
||||
// Returns true if all the extensions can be recognized. The extensions will be
|
||||
// appended in to the extensions parameter.
|
||||
// Returns false when there are unknown fields, in which case the data in the
|
||||
// extensions output parameter is not reliable and should be discarded.
|
||||
bool CollectExtensions(const Message& message,
|
||||
vector<const FieldDescriptor*>* extensions) {
|
||||
const Reflection* reflection = message.GetReflection();
|
||||
|
||||
// There are unknown fields that could be extensions, thus this call fails.
|
||||
if (reflection->GetUnknownFields(message).field_count() > 0) return false;
|
||||
|
||||
vector<const FieldDescriptor*> fields;
|
||||
reflection->ListFields(message, &fields);
|
||||
|
||||
for (int i = 0; i < fields.size(); i++) {
|
||||
if (fields[i]->is_extension()) extensions->push_back(fields[i]);
|
||||
|
||||
if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) {
|
||||
if (fields[i]->is_repeated()) {
|
||||
int size = reflection->FieldSize(message, fields[i]);
|
||||
for (int j = 0; j < size; j++) {
|
||||
const Message& sub_message =
|
||||
reflection->GetRepeatedMessage(message, fields[i], j);
|
||||
if (!CollectExtensions(sub_message, extensions)) return false;
|
||||
}
|
||||
} else {
|
||||
const Message& sub_message = reflection->GetMessage(message, fields[i]);
|
||||
if (!CollectExtensions(sub_message, extensions)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Finds all extensions in the given message and its sub-messages. If the
|
||||
// message contains unknown fields (which could be extensions), then those
|
||||
// extensions are defined in alternate_pool.
|
||||
// The message will be converted to a DynamicMessage backed by alternate_pool
|
||||
// in order to handle this case.
|
||||
void CollectExtensions(const FileDescriptorProto& file_proto,
|
||||
const DescriptorPool& alternate_pool,
|
||||
vector<const FieldDescriptor*>* extensions,
|
||||
const string& file_data) {
|
||||
if (!CollectExtensions(file_proto, extensions)) {
|
||||
// There are unknown fields in the file_proto, which are probably
|
||||
// extensions. We need to parse the data into a dynamic message based on the
|
||||
// builder-pool to find out all extensions.
|
||||
const Descriptor* file_proto_desc = alternate_pool.FindMessageTypeByName(
|
||||
file_proto.GetDescriptor()->full_name());
|
||||
GOOGLE_CHECK(file_proto_desc)
|
||||
<< "Find unknown fields in FileDescriptorProto when building "
|
||||
<< file_proto.name()
|
||||
<< ". It's likely that those fields are custom options, however, "
|
||||
"descriptor.proto is not in the transitive dependencies. "
|
||||
"This normally should not happen. Please report a bug.";
|
||||
DynamicMessageFactory factory;
|
||||
scoped_ptr<Message> dynamic_file_proto(
|
||||
factory.GetPrototype(file_proto_desc)->New());
|
||||
GOOGLE_CHECK(dynamic_file_proto.get() != NULL);
|
||||
GOOGLE_CHECK(dynamic_file_proto->ParseFromString(file_data));
|
||||
|
||||
// Collect the extensions again from the dynamic message. There should be no
|
||||
// more unknown fields this time, i.e. all the custom options should be
|
||||
// parsed as extensions now.
|
||||
extensions->clear();
|
||||
GOOGLE_CHECK(CollectExtensions(*dynamic_file_proto, extensions))
|
||||
<< "Find unknown fields in FileDescriptorProto when building "
|
||||
<< file_proto.name()
|
||||
<< ". It's likely that those fields are custom options, however, "
|
||||
"those options cannot be recognized in the builder pool. "
|
||||
"This normally should not happen. Please report a bug.";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
FileGenerator::FileGenerator(const FileDescriptor* file)
|
||||
: file_(file),
|
||||
java_package_(FileJavaPackage(file)),
|
||||
classname_(FileClassName(file)) {
|
||||
}
|
||||
|
||||
FileGenerator::~FileGenerator() {}
|
||||
|
||||
bool FileGenerator::Validate(string* error) {
|
||||
// Check that no class name matches the file's class name. This is a common
|
||||
// problem that leads to Java compile errors that can be hard to understand.
|
||||
// It's especially bad when using the java_multiple_files, since we would
|
||||
// end up overwriting the outer class with one of the inner ones.
|
||||
|
||||
bool found_conflict = false;
|
||||
for (int i = 0; i < file_->enum_type_count() && !found_conflict; i++) {
|
||||
if (file_->enum_type(i)->name() == classname_) {
|
||||
found_conflict = true;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < file_->message_type_count() && !found_conflict; i++) {
|
||||
if (file_->message_type(i)->name() == classname_) {
|
||||
found_conflict = true;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < file_->service_count() && !found_conflict; i++) {
|
||||
if (file_->service(i)->name() == classname_) {
|
||||
found_conflict = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_conflict) {
|
||||
error->assign(file_->name());
|
||||
error->append(
|
||||
": Cannot generate Java output because the file's outer class name, \"");
|
||||
error->append(classname_);
|
||||
error->append(
|
||||
"\", matches the name of one of the types declared inside it. "
|
||||
"Please either rename the type or use the java_outer_classname "
|
||||
"option to specify a different outer class name for the .proto file.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileGenerator::Generate(io::Printer* printer) {
|
||||
// We don't import anything because we refer to all classes by their
|
||||
// fully-qualified names in the generated source.
|
||||
printer->Print(
|
||||
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
|
||||
"// source: $filename$\n"
|
||||
"\n",
|
||||
"filename", file_->name());
|
||||
if (!java_package_.empty()) {
|
||||
printer->Print(
|
||||
"package $package$;\n"
|
||||
"\n",
|
||||
"package", java_package_);
|
||||
}
|
||||
printer->Print(
|
||||
"public final class $classname$ {\n"
|
||||
" private $classname$() {}\n",
|
||||
"classname", classname_);
|
||||
printer->Indent();
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
printer->Print(
|
||||
"public static void registerAllExtensions(\n"
|
||||
" com.google.protobuf.ExtensionRegistry$lite$ registry) {\n",
|
||||
"lite", HasDescriptorMethods(file_) ? "" : "Lite");
|
||||
|
||||
printer->Indent();
|
||||
|
||||
for (int i = 0; i < file_->extension_count(); i++) {
|
||||
ExtensionGenerator(file_->extension(i)).GenerateRegistrationCode(printer);
|
||||
}
|
||||
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
MessageGenerator(file_->message_type(i))
|
||||
.GenerateExtensionRegistrationCode(printer);
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n");
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
if (!file_->options().java_multiple_files()) {
|
||||
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||
EnumGenerator(file_->enum_type(i)).Generate(printer);
|
||||
}
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
MessageGenerator messageGenerator(file_->message_type(i));
|
||||
messageGenerator.GenerateInterface(printer);
|
||||
messageGenerator.Generate(printer);
|
||||
}
|
||||
if (HasGenericServices(file_)) {
|
||||
for (int i = 0; i < file_->service_count(); i++) {
|
||||
ServiceGenerator(file_->service(i)).Generate(printer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extensions must be generated in the outer class since they are values,
|
||||
// not classes.
|
||||
for (int i = 0; i < file_->extension_count(); i++) {
|
||||
ExtensionGenerator(file_->extension(i)).Generate(printer);
|
||||
}
|
||||
|
||||
// Static variables.
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
// TODO(kenton): Reuse MessageGenerator objects?
|
||||
MessageGenerator(file_->message_type(i)).GenerateStaticVariables(printer);
|
||||
}
|
||||
|
||||
printer->Print("\n");
|
||||
|
||||
if (HasDescriptorMethods(file_)) {
|
||||
GenerateEmbeddedDescriptor(printer);
|
||||
} else {
|
||||
printer->Print(
|
||||
"static {\n");
|
||||
printer->Indent();
|
||||
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
// TODO(kenton): Reuse MessageGenerator objects?
|
||||
MessageGenerator(file_->message_type(i))
|
||||
.GenerateStaticVariableInitializers(printer);
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n");
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"\n"
|
||||
"// @@protoc_insertion_point(outer_class_scope)\n");
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) {
|
||||
// Embed the descriptor. We simply serialize the entire FileDescriptorProto
|
||||
// and embed it as a string literal, which is parsed and built into real
|
||||
// descriptors at initialization time. We unfortunately have to put it in
|
||||
// a string literal, not a byte array, because apparently using a literal
|
||||
// byte array causes the Java compiler to generate *instructions* to
|
||||
// initialize each and every byte of the array, e.g. as if you typed:
|
||||
// b[0] = 123; b[1] = 456; b[2] = 789;
|
||||
// This makes huge bytecode files and can easily hit the compiler's internal
|
||||
// code size limits (error "code to large"). String literals are apparently
|
||||
// embedded raw, which is what we want.
|
||||
FileDescriptorProto file_proto;
|
||||
file_->CopyTo(&file_proto);
|
||||
|
||||
string file_data;
|
||||
file_proto.SerializeToString(&file_data);
|
||||
|
||||
printer->Print(
|
||||
"public static com.google.protobuf.Descriptors.FileDescriptor\n"
|
||||
" getDescriptor() {\n"
|
||||
" return descriptor;\n"
|
||||
"}\n"
|
||||
"private static com.google.protobuf.Descriptors.FileDescriptor\n"
|
||||
" descriptor;\n"
|
||||
"static {\n"
|
||||
" java.lang.String[] descriptorData = {\n");
|
||||
printer->Indent();
|
||||
printer->Indent();
|
||||
|
||||
// Only write 40 bytes per line.
|
||||
static const int kBytesPerLine = 40;
|
||||
for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
|
||||
if (i > 0) {
|
||||
// Every 400 lines, start a new string literal, in order to avoid the
|
||||
// 64k length limit.
|
||||
if (i % 400 == 0) {
|
||||
printer->Print(",\n");
|
||||
} else {
|
||||
printer->Print(" +\n");
|
||||
}
|
||||
}
|
||||
printer->Print("\"$data$\"",
|
||||
"data", CEscape(file_data.substr(i, kBytesPerLine)));
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print("\n};\n");
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Create the InternalDescriptorAssigner.
|
||||
|
||||
printer->Print(
|
||||
"com.google.protobuf.Descriptors.FileDescriptor."
|
||||
"InternalDescriptorAssigner assigner =\n"
|
||||
" new com.google.protobuf.Descriptors.FileDescriptor."
|
||||
"InternalDescriptorAssigner() {\n"
|
||||
" public com.google.protobuf.ExtensionRegistry assignDescriptors(\n"
|
||||
" com.google.protobuf.Descriptors.FileDescriptor root) {\n"
|
||||
" descriptor = root;\n");
|
||||
|
||||
printer->Indent();
|
||||
printer->Indent();
|
||||
printer->Indent();
|
||||
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
// TODO(kenton): Reuse MessageGenerator objects?
|
||||
MessageGenerator(file_->message_type(i))
|
||||
.GenerateStaticVariableInitializers(printer);
|
||||
}
|
||||
for (int i = 0; i < file_->extension_count(); i++) {
|
||||
// TODO(kenton): Reuse ExtensionGenerator objects?
|
||||
ExtensionGenerator(file_->extension(i))
|
||||
.GenerateNonNestedInitializationCode(printer);
|
||||
}
|
||||
|
||||
// Proto compiler builds a DescriptorPool, which holds all the descriptors to
|
||||
// generate, when processing the ".proto" files. We call this DescriptorPool
|
||||
// the parsed pool (a.k.a. file_->pool()).
|
||||
//
|
||||
// Note that when users try to extend the (.*)DescriptorProto in their
|
||||
// ".proto" files, it does not affect the pre-built FileDescriptorProto class
|
||||
// in proto compiler. When we put the descriptor data in the file_proto, those
|
||||
// extensions become unknown fields.
|
||||
//
|
||||
// Now we need to find out all the extension value to the (.*)DescriptorProto
|
||||
// in the file_proto message, and prepare an ExtensionRegistry to return.
|
||||
//
|
||||
// To find those extensions, we need to parse the data into a dynamic message
|
||||
// of the FileDescriptor based on the builder-pool, then we can use
|
||||
// reflections to find all extension fields
|
||||
vector<const FieldDescriptor*> extensions;
|
||||
CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
|
||||
|
||||
if (extensions.size() > 0) {
|
||||
// Must construct an ExtensionRegistry containing all existing extensions
|
||||
// and return it.
|
||||
printer->Print(
|
||||
"com.google.protobuf.ExtensionRegistry registry =\n"
|
||||
" com.google.protobuf.ExtensionRegistry.newInstance();\n");
|
||||
for (int i = 0; i < extensions.size(); i++) {
|
||||
ExtensionGenerator(extensions[i]).GenerateRegistrationCode(printer);
|
||||
}
|
||||
printer->Print(
|
||||
"return registry;\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
"return null;\n");
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Outdent();
|
||||
printer->Outdent();
|
||||
|
||||
printer->Print(
|
||||
" }\n"
|
||||
" };\n");
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Invoke internalBuildGeneratedFileFrom() to build the file.
|
||||
|
||||
printer->Print(
|
||||
"com.google.protobuf.Descriptors.FileDescriptor\n"
|
||||
" .internalBuildGeneratedFileFrom(descriptorData,\n"
|
||||
" new com.google.protobuf.Descriptors.FileDescriptor[] {\n");
|
||||
|
||||
for (int i = 0; i < file_->dependency_count(); i++) {
|
||||
if (ShouldIncludeDependency(file_->dependency(i))) {
|
||||
printer->Print(
|
||||
" $dependency$.getDescriptor(),\n",
|
||||
"dependency", ClassName(file_->dependency(i)));
|
||||
}
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
" }, assigner);\n");
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n");
|
||||
}
|
||||
|
||||
template<typename GeneratorClass, typename DescriptorClass>
|
||||
static void GenerateSibling(const string& package_dir,
|
||||
const string& java_package,
|
||||
const DescriptorClass* descriptor,
|
||||
GeneratorContext* context,
|
||||
vector<string>* file_list,
|
||||
const string& name_suffix,
|
||||
void (GeneratorClass::*pfn)(io::Printer* printer)) {
|
||||
string filename = package_dir + descriptor->name() + name_suffix + ".java";
|
||||
file_list->push_back(filename);
|
||||
|
||||
scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
|
||||
io::Printer printer(output.get(), '$');
|
||||
|
||||
printer.Print(
|
||||
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
|
||||
"// source: $filename$\n"
|
||||
"\n",
|
||||
"filename", descriptor->file()->name());
|
||||
if (!java_package.empty()) {
|
||||
printer.Print(
|
||||
"package $package$;\n"
|
||||
"\n",
|
||||
"package", java_package);
|
||||
}
|
||||
|
||||
GeneratorClass generator(descriptor);
|
||||
(generator.*pfn)(&printer);
|
||||
}
|
||||
|
||||
void FileGenerator::GenerateSiblings(const string& package_dir,
|
||||
GeneratorContext* context,
|
||||
vector<string>* file_list) {
|
||||
if (file_->options().java_multiple_files()) {
|
||||
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||
GenerateSibling<EnumGenerator>(package_dir, java_package_,
|
||||
file_->enum_type(i),
|
||||
context, file_list, "",
|
||||
&EnumGenerator::Generate);
|
||||
}
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
GenerateSibling<MessageGenerator>(package_dir, java_package_,
|
||||
file_->message_type(i),
|
||||
context, file_list, "OrBuilder",
|
||||
&MessageGenerator::GenerateInterface);
|
||||
GenerateSibling<MessageGenerator>(package_dir, java_package_,
|
||||
file_->message_type(i),
|
||||
context, file_list, "",
|
||||
&MessageGenerator::Generate);
|
||||
}
|
||||
if (HasGenericServices(file_)) {
|
||||
for (int i = 0; i < file_->service_count(); i++) {
|
||||
GenerateSibling<ServiceGenerator>(package_dir, java_package_,
|
||||
file_->service(i),
|
||||
context, file_list, "",
|
||||
&ServiceGenerator::Generate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace java
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -1,128 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/compiler/java/java_generator.h>
|
||||
#include <google/protobuf/compiler/java/java_file.h>
|
||||
#include <google/protobuf/compiler/java/java_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 java {
|
||||
|
||||
|
||||
JavaGenerator::JavaGenerator() {}
|
||||
JavaGenerator::~JavaGenerator() {}
|
||||
|
||||
bool JavaGenerator::Generate(const FileDescriptor* file,
|
||||
const string& parameter,
|
||||
GeneratorContext* context,
|
||||
string* error) const {
|
||||
// -----------------------------------------------------------------
|
||||
// parse generator options
|
||||
|
||||
// Name a file where we will write a list of generated file names, one
|
||||
// per line.
|
||||
string output_list_file;
|
||||
|
||||
|
||||
vector<pair<string, string> > options;
|
||||
ParseGeneratorParameter(parameter, &options);
|
||||
|
||||
for (int i = 0; i < options.size(); i++) {
|
||||
if (options[i].first == "output_list_file") {
|
||||
output_list_file = options[i].second;
|
||||
} else {
|
||||
*error = "Unknown generator option: " + options[i].first;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
|
||||
if (file->options().optimize_for() == FileOptions::LITE_RUNTIME &&
|
||||
file->options().java_generate_equals_and_hash()) {
|
||||
*error = "The \"java_generate_equals_and_hash\" option is incompatible "
|
||||
"with \"optimize_for = LITE_RUNTIME\". You must optimize for "
|
||||
"SPEED or CODE_SIZE if you want to use this option.";
|
||||
return false;
|
||||
}
|
||||
|
||||
FileGenerator file_generator(file);
|
||||
if (!file_generator.Validate(error)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string package_dir = JavaPackageToDir(file_generator.java_package());
|
||||
|
||||
vector<string> all_files;
|
||||
|
||||
string java_filename = package_dir;
|
||||
java_filename += file_generator.classname();
|
||||
java_filename += ".java";
|
||||
all_files.push_back(java_filename);
|
||||
|
||||
// Generate main java file.
|
||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
context->Open(java_filename));
|
||||
io::Printer printer(output.get(), '$');
|
||||
file_generator.Generate(&printer);
|
||||
|
||||
// Generate sibling files.
|
||||
file_generator.GenerateSiblings(package_dir, context, &all_files);
|
||||
|
||||
// Generate output list if requested.
|
||||
if (!output_list_file.empty()) {
|
||||
// Generate output list. This is just a simple text file placed in a
|
||||
// deterministic location which lists the .java files being generated.
|
||||
scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
|
||||
context->Open(output_list_file));
|
||||
io::Printer srclist_printer(srclist_raw_output.get(), '$');
|
||||
for (int i = 0; i < all_files.size(); i++) {
|
||||
srclist_printer.Print("$filename$\n", "filename", all_files[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace java
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -1,220 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace java {
|
||||
|
||||
// Commonly-used separator comments. Thick is a line of '=', thin is a line
|
||||
// of '-'.
|
||||
extern const char kThickSeparator[];
|
||||
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 UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field);
|
||||
|
||||
// Similar, but for method names. (Typically, this merely has the effect
|
||||
// of lower-casing the first letter of the name.)
|
||||
string UnderscoresToCamelCase(const MethodDescriptor* method);
|
||||
|
||||
// Strips ".proto" or ".protodevel" from the end of a filename.
|
||||
string StripProto(const string& filename);
|
||||
|
||||
// Gets the unqualified class name for the file. Each .proto file becomes a
|
||||
// single Java class, with all its contents nested in that class.
|
||||
string FileClassName(const FileDescriptor* file);
|
||||
|
||||
// Returns the file's Java package name.
|
||||
string FileJavaPackage(const FileDescriptor* file);
|
||||
|
||||
// Returns output directory for the given package name.
|
||||
string JavaPackageToDir(string package_name);
|
||||
|
||||
// Converts the given fully-qualified name in the proto namespace to its
|
||||
// fully-qualified name in the Java namespace, given that it is in the given
|
||||
// file.
|
||||
string ToJavaName(const string& full_name, const FileDescriptor* file);
|
||||
|
||||
// These return the fully-qualified class name corresponding to the given
|
||||
// descriptor.
|
||||
string ClassName(const Descriptor* descriptor);
|
||||
string ClassName(const EnumDescriptor* descriptor);
|
||||
string ClassName(const ServiceDescriptor* descriptor);
|
||||
string ClassName(const FileDescriptor* descriptor);
|
||||
|
||||
inline string ExtensionIdentifierName(const FieldDescriptor* descriptor) {
|
||||
return ToJavaName(descriptor->full_name(), descriptor->file());
|
||||
}
|
||||
|
||||
// Get the unqualified name that should be used for a field's field
|
||||
// number constant.
|
||||
string FieldConstantName(const FieldDescriptor *field);
|
||||
|
||||
// Returns the type of the FieldDescriptor.
|
||||
// This does nothing interesting for the open source release, but is used for
|
||||
// hacks that improve compatability with version 1 protocol buffers at Google.
|
||||
FieldDescriptor::Type GetType(const FieldDescriptor* field);
|
||||
|
||||
enum JavaType {
|
||||
JAVATYPE_INT,
|
||||
JAVATYPE_LONG,
|
||||
JAVATYPE_FLOAT,
|
||||
JAVATYPE_DOUBLE,
|
||||
JAVATYPE_BOOLEAN,
|
||||
JAVATYPE_STRING,
|
||||
JAVATYPE_BYTES,
|
||||
JAVATYPE_ENUM,
|
||||
JAVATYPE_MESSAGE
|
||||
};
|
||||
|
||||
JavaType GetJavaType(const FieldDescriptor* field);
|
||||
|
||||
// Get the fully-qualified class name for a boxed primitive type, e.g.
|
||||
// "java.lang.Integer" for JAVATYPE_INT. Returns NULL for enum and message
|
||||
// types.
|
||||
const char* BoxedPrimitiveTypeName(JavaType type);
|
||||
|
||||
string DefaultValue(const FieldDescriptor* field);
|
||||
bool IsDefaultValueJavaDefault(const FieldDescriptor* field);
|
||||
|
||||
// Does this message class keep track of unknown fields?
|
||||
inline bool HasUnknownFields(const Descriptor* descriptor) {
|
||||
return descriptor->file()->options().optimize_for() !=
|
||||
FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
|
||||
// Does this message class have generated parsing, serialization, and other
|
||||
// standard methods for which reflection-based fallback implementations exist?
|
||||
inline bool HasGeneratedMethods(const Descriptor* descriptor) {
|
||||
return descriptor->file()->options().optimize_for() !=
|
||||
FileOptions::CODE_SIZE;
|
||||
}
|
||||
|
||||
// Does this message have specialized equals() and hashCode() methods?
|
||||
inline bool HasEqualsAndHashCode(const Descriptor* descriptor) {
|
||||
return descriptor->file()->options().java_generate_equals_and_hash();
|
||||
}
|
||||
|
||||
// Does this message class have descriptor and reflection methods?
|
||||
inline bool HasDescriptorMethods(const Descriptor* descriptor) {
|
||||
return descriptor->file()->options().optimize_for() !=
|
||||
FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
inline bool HasDescriptorMethods(const EnumDescriptor* descriptor) {
|
||||
return descriptor->file()->options().optimize_for() !=
|
||||
FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
inline bool HasDescriptorMethods(const FileDescriptor* descriptor) {
|
||||
return descriptor->options().optimize_for() !=
|
||||
FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
|
||||
inline bool HasNestedBuilders(const Descriptor* descriptor) {
|
||||
// The proto-lite version doesn't support nested builders.
|
||||
return descriptor->file()->options().optimize_for() !=
|
||||
FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
|
||||
// Should we generate generic services for this file?
|
||||
inline bool HasGenericServices(const FileDescriptor *file) {
|
||||
return file->service_count() > 0 &&
|
||||
file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
|
||||
file->options().java_generic_services();
|
||||
}
|
||||
|
||||
|
||||
// Methods for shared bitfields.
|
||||
|
||||
// Gets the name of the shared bitfield for the given index.
|
||||
string GetBitFieldName(int index);
|
||||
|
||||
// Gets the name of the shared bitfield for the given bit index.
|
||||
// Effectively, GetBitFieldName(bitIndex / 32)
|
||||
string GetBitFieldNameForBit(int bitIndex);
|
||||
|
||||
// Generates the java code for the expression that returns the boolean value
|
||||
// of the bit of the shared bitfields for the given bit index.
|
||||
// Example: "((bitField1_ & 0x04) == 0x04)"
|
||||
string GenerateGetBit(int bitIndex);
|
||||
|
||||
// Generates the java code for the expression that sets the bit of the shared
|
||||
// bitfields for the given bit index.
|
||||
// Example: "bitField1_ = (bitField1_ | 0x04)"
|
||||
string GenerateSetBit(int bitIndex);
|
||||
|
||||
// Generates the java code for the expression that clears the bit of the shared
|
||||
// bitfields for the given bit index.
|
||||
// Example: "bitField1_ = (bitField1_ & ~0x04)"
|
||||
string GenerateClearBit(int bitIndex);
|
||||
|
||||
// Does the same as GenerateGetBit but operates on the bit field on a local
|
||||
// variable. This is used by the builder to copy the value in the builder to
|
||||
// the message.
|
||||
// Example: "((from_bitField1_ & 0x04) == 0x04)"
|
||||
string GenerateGetBitFromLocal(int bitIndex);
|
||||
|
||||
// Does the same as GenerateSetBit but operates on the bit field on a local
|
||||
// variable. This is used by the builder to copy the value in the builder to
|
||||
// the message.
|
||||
// Example: "to_bitField1_ = (to_bitField1_ | 0x04)"
|
||||
string GenerateSetBitToLocal(int bitIndex);
|
||||
|
||||
// Does the same as GenerateGetBit but operates on the bit field on a local
|
||||
// variable. This is used by the parsing constructor to record if a repeated
|
||||
// field is mutable.
|
||||
// Example: "((mutable_bitField1_ & 0x04) == 0x04)"
|
||||
string GenerateGetBitMutableLocal(int bitIndex);
|
||||
|
||||
// Does the same as GenerateSetBit but operates on the bit field on a local
|
||||
// variable. This is used by the parsing constructor to record if a repeated
|
||||
// field is mutable.
|
||||
// Example: "mutable_bitField1_ = (mutable_bitField1_ | 0x04)"
|
||||
string GenerateSetBitMutableLocal(int bitIndex);
|
||||
|
||||
} // namespace java
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,856 +0,0 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/compiler/plugin.proto
|
||||
|
||||
#ifndef PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
|
||||
#define PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#if GOOGLE_PROTOBUF_VERSION < 2005000
|
||||
#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 2005000 < 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.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
#include "google/protobuf/descriptor.pb.h"
|
||||
// @@protoc_insertion_point(includes)
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
|
||||
// Internal implementation detail -- do not call these.
|
||||
void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||
void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||
void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||
|
||||
class CodeGeneratorRequest;
|
||||
class CodeGeneratorResponse;
|
||||
class CodeGeneratorResponse_File;
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message {
|
||||
public:
|
||||
CodeGeneratorRequest();
|
||||
virtual ~CodeGeneratorRequest();
|
||||
|
||||
CodeGeneratorRequest(const CodeGeneratorRequest& from);
|
||||
|
||||
inline CodeGeneratorRequest& operator=(const CodeGeneratorRequest& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
|
||||
return _unknown_fields_;
|
||||
}
|
||||
|
||||
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
|
||||
return &_unknown_fields_;
|
||||
}
|
||||
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const CodeGeneratorRequest& default_instance();
|
||||
|
||||
void Swap(CodeGeneratorRequest* other);
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
CodeGeneratorRequest* New() const;
|
||||
void CopyFrom(const ::google::protobuf::Message& from);
|
||||
void MergeFrom(const ::google::protobuf::Message& from);
|
||||
void CopyFrom(const CodeGeneratorRequest& from);
|
||||
void MergeFrom(const CodeGeneratorRequest& from);
|
||||
void Clear();
|
||||
bool IsInitialized() const;
|
||||
|
||||
int ByteSize() const;
|
||||
bool MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input);
|
||||
void SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const;
|
||||
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
|
||||
int GetCachedSize() const { return _cached_size_; }
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const;
|
||||
public:
|
||||
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// repeated string file_to_generate = 1;
|
||||
inline int file_to_generate_size() const;
|
||||
inline 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();
|
||||
|
||||
// optional string parameter = 2;
|
||||
inline bool has_parameter() const;
|
||||
inline 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);
|
||||
|
||||
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
||||
inline int proto_file_size() const;
|
||||
inline 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 >&
|
||||
proto_file() const;
|
||||
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
|
||||
mutable_proto_file();
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest)
|
||||
private:
|
||||
inline void set_has_parameter();
|
||||
inline void clear_has_parameter();
|
||||
|
||||
::google::protobuf::UnknownFieldSet _unknown_fields_;
|
||||
|
||||
::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_;
|
||||
::std::string* parameter_;
|
||||
::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_;
|
||||
|
||||
mutable int _cached_size_;
|
||||
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
|
||||
|
||||
friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||
|
||||
void InitAsDefaultInstance();
|
||||
static CodeGeneratorRequest* default_instance_;
|
||||
};
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::Message {
|
||||
public:
|
||||
CodeGeneratorResponse_File();
|
||||
virtual ~CodeGeneratorResponse_File();
|
||||
|
||||
CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from);
|
||||
|
||||
inline CodeGeneratorResponse_File& operator=(const CodeGeneratorResponse_File& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
|
||||
return _unknown_fields_;
|
||||
}
|
||||
|
||||
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
|
||||
return &_unknown_fields_;
|
||||
}
|
||||
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const CodeGeneratorResponse_File& default_instance();
|
||||
|
||||
void Swap(CodeGeneratorResponse_File* other);
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
CodeGeneratorResponse_File* New() const;
|
||||
void CopyFrom(const ::google::protobuf::Message& from);
|
||||
void MergeFrom(const ::google::protobuf::Message& from);
|
||||
void CopyFrom(const CodeGeneratorResponse_File& from);
|
||||
void MergeFrom(const CodeGeneratorResponse_File& from);
|
||||
void Clear();
|
||||
bool IsInitialized() const;
|
||||
|
||||
int ByteSize() const;
|
||||
bool MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input);
|
||||
void SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const;
|
||||
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
|
||||
int GetCachedSize() const { return _cached_size_; }
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const;
|
||||
public:
|
||||
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// optional string name = 1;
|
||||
inline bool has_name() const;
|
||||
inline 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);
|
||||
|
||||
// optional string insertion_point = 2;
|
||||
inline bool has_insertion_point() const;
|
||||
inline 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);
|
||||
|
||||
// optional string content = 15;
|
||||
inline bool has_content() const;
|
||||
inline 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);
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
|
||||
private:
|
||||
inline void set_has_name();
|
||||
inline void clear_has_name();
|
||||
inline void set_has_insertion_point();
|
||||
inline void clear_has_insertion_point();
|
||||
inline void set_has_content();
|
||||
inline void clear_has_content();
|
||||
|
||||
::google::protobuf::UnknownFieldSet _unknown_fields_;
|
||||
|
||||
::std::string* name_;
|
||||
::std::string* insertion_point_;
|
||||
::std::string* content_;
|
||||
|
||||
mutable int _cached_size_;
|
||||
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
|
||||
|
||||
friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||
|
||||
void InitAsDefaultInstance();
|
||||
static CodeGeneratorResponse_File* default_instance_;
|
||||
};
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Message {
|
||||
public:
|
||||
CodeGeneratorResponse();
|
||||
virtual ~CodeGeneratorResponse();
|
||||
|
||||
CodeGeneratorResponse(const CodeGeneratorResponse& from);
|
||||
|
||||
inline CodeGeneratorResponse& operator=(const CodeGeneratorResponse& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
|
||||
return _unknown_fields_;
|
||||
}
|
||||
|
||||
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
|
||||
return &_unknown_fields_;
|
||||
}
|
||||
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const CodeGeneratorResponse& default_instance();
|
||||
|
||||
void Swap(CodeGeneratorResponse* other);
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
CodeGeneratorResponse* New() const;
|
||||
void CopyFrom(const ::google::protobuf::Message& from);
|
||||
void MergeFrom(const ::google::protobuf::Message& from);
|
||||
void CopyFrom(const CodeGeneratorResponse& from);
|
||||
void MergeFrom(const CodeGeneratorResponse& from);
|
||||
void Clear();
|
||||
bool IsInitialized() const;
|
||||
|
||||
int ByteSize() const;
|
||||
bool MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input);
|
||||
void SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const;
|
||||
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
|
||||
int GetCachedSize() const { return _cached_size_; }
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const;
|
||||
public:
|
||||
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
typedef CodeGeneratorResponse_File File;
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// optional string error = 1;
|
||||
inline bool has_error() const;
|
||||
inline 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);
|
||||
|
||||
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
|
||||
inline int file_size() const;
|
||||
inline 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 >&
|
||||
file() const;
|
||||
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
|
||||
mutable_file();
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
|
||||
private:
|
||||
inline void set_has_error();
|
||||
inline void clear_has_error();
|
||||
|
||||
::google::protobuf::UnknownFieldSet _unknown_fields_;
|
||||
|
||||
::std::string* error_;
|
||||
::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_;
|
||||
|
||||
mutable int _cached_size_;
|
||||
::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
|
||||
|
||||
friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
|
||||
|
||||
void InitAsDefaultInstance();
|
||||
static CodeGeneratorResponse* default_instance_;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// CodeGeneratorRequest
|
||||
|
||||
// repeated string file_to_generate = 1;
|
||||
inline int CodeGeneratorRequest::file_to_generate_size() const {
|
||||
return file_to_generate_.size();
|
||||
}
|
||||
inline void CodeGeneratorRequest::clear_file_to_generate() {
|
||||
file_to_generate_.Clear();
|
||||
}
|
||||
inline const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const {
|
||||
return file_to_generate_.Get(index);
|
||||
}
|
||||
inline ::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) {
|
||||
return file_to_generate_.Mutable(index);
|
||||
}
|
||||
inline void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) {
|
||||
file_to_generate_.Mutable(index)->assign(value);
|
||||
}
|
||||
inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) {
|
||||
file_to_generate_.Mutable(index)->assign(value);
|
||||
}
|
||||
inline 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);
|
||||
}
|
||||
inline ::std::string* CodeGeneratorRequest::add_file_to_generate() {
|
||||
return file_to_generate_.Add();
|
||||
}
|
||||
inline void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) {
|
||||
file_to_generate_.Add()->assign(value);
|
||||
}
|
||||
inline void CodeGeneratorRequest::add_file_to_generate(const char* value) {
|
||||
file_to_generate_.Add()->assign(value);
|
||||
}
|
||||
inline void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) {
|
||||
file_to_generate_.Add()->assign(reinterpret_cast<const char*>(value), size);
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
|
||||
CodeGeneratorRequest::file_to_generate() const {
|
||||
return file_to_generate_;
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField< ::std::string>*
|
||||
CodeGeneratorRequest::mutable_file_to_generate() {
|
||||
return &file_to_generate_;
|
||||
}
|
||||
|
||||
// optional string parameter = 2;
|
||||
inline bool CodeGeneratorRequest::has_parameter() const {
|
||||
return (_has_bits_[0] & 0x00000002u) != 0;
|
||||
}
|
||||
inline void CodeGeneratorRequest::set_has_parameter() {
|
||||
_has_bits_[0] |= 0x00000002u;
|
||||
}
|
||||
inline void CodeGeneratorRequest::clear_has_parameter() {
|
||||
_has_bits_[0] &= ~0x00000002u;
|
||||
}
|
||||
inline void CodeGeneratorRequest::clear_parameter() {
|
||||
if (parameter_ != &::google::protobuf::internal::kEmptyString) {
|
||||
parameter_->clear();
|
||||
}
|
||||
clear_has_parameter();
|
||||
}
|
||||
inline const ::std::string& CodeGeneratorRequest::parameter() const {
|
||||
return *parameter_;
|
||||
}
|
||||
inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
|
||||
set_has_parameter();
|
||||
if (parameter_ == &::google::protobuf::internal::kEmptyString) {
|
||||
parameter_ = new ::std::string;
|
||||
}
|
||||
parameter_->assign(value);
|
||||
}
|
||||
inline void CodeGeneratorRequest::set_parameter(const char* value) {
|
||||
set_has_parameter();
|
||||
if (parameter_ == &::google::protobuf::internal::kEmptyString) {
|
||||
parameter_ = new ::std::string;
|
||||
}
|
||||
parameter_->assign(value);
|
||||
}
|
||||
inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
|
||||
set_has_parameter();
|
||||
if (parameter_ == &::google::protobuf::internal::kEmptyString) {
|
||||
parameter_ = new ::std::string;
|
||||
}
|
||||
parameter_->assign(reinterpret_cast<const char*>(value), size);
|
||||
}
|
||||
inline ::std::string* CodeGeneratorRequest::mutable_parameter() {
|
||||
set_has_parameter();
|
||||
if (parameter_ == &::google::protobuf::internal::kEmptyString) {
|
||||
parameter_ = new ::std::string;
|
||||
}
|
||||
return parameter_;
|
||||
}
|
||||
inline ::std::string* CodeGeneratorRequest::release_parameter() {
|
||||
clear_has_parameter();
|
||||
if (parameter_ == &::google::protobuf::internal::kEmptyString) {
|
||||
return NULL;
|
||||
} else {
|
||||
::std::string* temp = parameter_;
|
||||
parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) {
|
||||
if (parameter_ != &::google::protobuf::internal::kEmptyString) {
|
||||
delete parameter_;
|
||||
}
|
||||
if (parameter) {
|
||||
set_has_parameter();
|
||||
parameter_ = parameter;
|
||||
} else {
|
||||
clear_has_parameter();
|
||||
parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||
}
|
||||
}
|
||||
|
||||
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
||||
inline int CodeGeneratorRequest::proto_file_size() const {
|
||||
return proto_file_.size();
|
||||
}
|
||||
inline void CodeGeneratorRequest::clear_proto_file() {
|
||||
proto_file_.Clear();
|
||||
}
|
||||
inline const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
|
||||
return proto_file_.Get(index);
|
||||
}
|
||||
inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) {
|
||||
return proto_file_.Mutable(index);
|
||||
}
|
||||
inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
|
||||
return proto_file_.Add();
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
|
||||
CodeGeneratorRequest::proto_file() const {
|
||||
return proto_file_;
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
|
||||
CodeGeneratorRequest::mutable_proto_file() {
|
||||
return &proto_file_;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
// CodeGeneratorResponse_File
|
||||
|
||||
// optional string name = 1;
|
||||
inline bool CodeGeneratorResponse_File::has_name() const {
|
||||
return (_has_bits_[0] & 0x00000001u) != 0;
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_has_name() {
|
||||
_has_bits_[0] |= 0x00000001u;
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::clear_has_name() {
|
||||
_has_bits_[0] &= ~0x00000001u;
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::clear_name() {
|
||||
if (name_ != &::google::protobuf::internal::kEmptyString) {
|
||||
name_->clear();
|
||||
}
|
||||
clear_has_name();
|
||||
}
|
||||
inline const ::std::string& CodeGeneratorResponse_File::name() const {
|
||||
return *name_;
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
|
||||
set_has_name();
|
||||
if (name_ == &::google::protobuf::internal::kEmptyString) {
|
||||
name_ = new ::std::string;
|
||||
}
|
||||
name_->assign(value);
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_name(const char* value) {
|
||||
set_has_name();
|
||||
if (name_ == &::google::protobuf::internal::kEmptyString) {
|
||||
name_ = new ::std::string;
|
||||
}
|
||||
name_->assign(value);
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
|
||||
set_has_name();
|
||||
if (name_ == &::google::protobuf::internal::kEmptyString) {
|
||||
name_ = new ::std::string;
|
||||
}
|
||||
name_->assign(reinterpret_cast<const char*>(value), size);
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse_File::mutable_name() {
|
||||
set_has_name();
|
||||
if (name_ == &::google::protobuf::internal::kEmptyString) {
|
||||
name_ = new ::std::string;
|
||||
}
|
||||
return name_;
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse_File::release_name() {
|
||||
clear_has_name();
|
||||
if (name_ == &::google::protobuf::internal::kEmptyString) {
|
||||
return NULL;
|
||||
} else {
|
||||
::std::string* temp = name_;
|
||||
name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) {
|
||||
if (name_ != &::google::protobuf::internal::kEmptyString) {
|
||||
delete name_;
|
||||
}
|
||||
if (name) {
|
||||
set_has_name();
|
||||
name_ = name;
|
||||
} else {
|
||||
clear_has_name();
|
||||
name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||
}
|
||||
}
|
||||
|
||||
// optional string insertion_point = 2;
|
||||
inline bool CodeGeneratorResponse_File::has_insertion_point() const {
|
||||
return (_has_bits_[0] & 0x00000002u) != 0;
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_has_insertion_point() {
|
||||
_has_bits_[0] |= 0x00000002u;
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::clear_has_insertion_point() {
|
||||
_has_bits_[0] &= ~0x00000002u;
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::clear_insertion_point() {
|
||||
if (insertion_point_ != &::google::protobuf::internal::kEmptyString) {
|
||||
insertion_point_->clear();
|
||||
}
|
||||
clear_has_insertion_point();
|
||||
}
|
||||
inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
|
||||
return *insertion_point_;
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
|
||||
set_has_insertion_point();
|
||||
if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
|
||||
insertion_point_ = new ::std::string;
|
||||
}
|
||||
insertion_point_->assign(value);
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
|
||||
set_has_insertion_point();
|
||||
if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
|
||||
insertion_point_ = new ::std::string;
|
||||
}
|
||||
insertion_point_->assign(value);
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
|
||||
set_has_insertion_point();
|
||||
if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
|
||||
insertion_point_ = new ::std::string;
|
||||
}
|
||||
insertion_point_->assign(reinterpret_cast<const char*>(value), size);
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
|
||||
set_has_insertion_point();
|
||||
if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
|
||||
insertion_point_ = new ::std::string;
|
||||
}
|
||||
return insertion_point_;
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() {
|
||||
clear_has_insertion_point();
|
||||
if (insertion_point_ == &::google::protobuf::internal::kEmptyString) {
|
||||
return NULL;
|
||||
} else {
|
||||
::std::string* temp = insertion_point_;
|
||||
insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) {
|
||||
if (insertion_point_ != &::google::protobuf::internal::kEmptyString) {
|
||||
delete insertion_point_;
|
||||
}
|
||||
if (insertion_point) {
|
||||
set_has_insertion_point();
|
||||
insertion_point_ = insertion_point;
|
||||
} else {
|
||||
clear_has_insertion_point();
|
||||
insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||
}
|
||||
}
|
||||
|
||||
// optional string content = 15;
|
||||
inline bool CodeGeneratorResponse_File::has_content() const {
|
||||
return (_has_bits_[0] & 0x00000004u) != 0;
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_has_content() {
|
||||
_has_bits_[0] |= 0x00000004u;
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::clear_has_content() {
|
||||
_has_bits_[0] &= ~0x00000004u;
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::clear_content() {
|
||||
if (content_ != &::google::protobuf::internal::kEmptyString) {
|
||||
content_->clear();
|
||||
}
|
||||
clear_has_content();
|
||||
}
|
||||
inline const ::std::string& CodeGeneratorResponse_File::content() const {
|
||||
return *content_;
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
|
||||
set_has_content();
|
||||
if (content_ == &::google::protobuf::internal::kEmptyString) {
|
||||
content_ = new ::std::string;
|
||||
}
|
||||
content_->assign(value);
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_content(const char* value) {
|
||||
set_has_content();
|
||||
if (content_ == &::google::protobuf::internal::kEmptyString) {
|
||||
content_ = new ::std::string;
|
||||
}
|
||||
content_->assign(value);
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
|
||||
set_has_content();
|
||||
if (content_ == &::google::protobuf::internal::kEmptyString) {
|
||||
content_ = new ::std::string;
|
||||
}
|
||||
content_->assign(reinterpret_cast<const char*>(value), size);
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse_File::mutable_content() {
|
||||
set_has_content();
|
||||
if (content_ == &::google::protobuf::internal::kEmptyString) {
|
||||
content_ = new ::std::string;
|
||||
}
|
||||
return content_;
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse_File::release_content() {
|
||||
clear_has_content();
|
||||
if (content_ == &::google::protobuf::internal::kEmptyString) {
|
||||
return NULL;
|
||||
} else {
|
||||
::std::string* temp = content_;
|
||||
content_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) {
|
||||
if (content_ != &::google::protobuf::internal::kEmptyString) {
|
||||
delete content_;
|
||||
}
|
||||
if (content) {
|
||||
set_has_content();
|
||||
content_ = content;
|
||||
} else {
|
||||
clear_has_content();
|
||||
content_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
// CodeGeneratorResponse
|
||||
|
||||
// optional string error = 1;
|
||||
inline bool CodeGeneratorResponse::has_error() const {
|
||||
return (_has_bits_[0] & 0x00000001u) != 0;
|
||||
}
|
||||
inline void CodeGeneratorResponse::set_has_error() {
|
||||
_has_bits_[0] |= 0x00000001u;
|
||||
}
|
||||
inline void CodeGeneratorResponse::clear_has_error() {
|
||||
_has_bits_[0] &= ~0x00000001u;
|
||||
}
|
||||
inline void CodeGeneratorResponse::clear_error() {
|
||||
if (error_ != &::google::protobuf::internal::kEmptyString) {
|
||||
error_->clear();
|
||||
}
|
||||
clear_has_error();
|
||||
}
|
||||
inline const ::std::string& CodeGeneratorResponse::error() const {
|
||||
return *error_;
|
||||
}
|
||||
inline void CodeGeneratorResponse::set_error(const ::std::string& value) {
|
||||
set_has_error();
|
||||
if (error_ == &::google::protobuf::internal::kEmptyString) {
|
||||
error_ = new ::std::string;
|
||||
}
|
||||
error_->assign(value);
|
||||
}
|
||||
inline void CodeGeneratorResponse::set_error(const char* value) {
|
||||
set_has_error();
|
||||
if (error_ == &::google::protobuf::internal::kEmptyString) {
|
||||
error_ = new ::std::string;
|
||||
}
|
||||
error_->assign(value);
|
||||
}
|
||||
inline void CodeGeneratorResponse::set_error(const char* value, size_t size) {
|
||||
set_has_error();
|
||||
if (error_ == &::google::protobuf::internal::kEmptyString) {
|
||||
error_ = new ::std::string;
|
||||
}
|
||||
error_->assign(reinterpret_cast<const char*>(value), size);
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse::mutable_error() {
|
||||
set_has_error();
|
||||
if (error_ == &::google::protobuf::internal::kEmptyString) {
|
||||
error_ = new ::std::string;
|
||||
}
|
||||
return error_;
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse::release_error() {
|
||||
clear_has_error();
|
||||
if (error_ == &::google::protobuf::internal::kEmptyString) {
|
||||
return NULL;
|
||||
} else {
|
||||
::std::string* temp = error_;
|
||||
error_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
|
||||
if (error_ != &::google::protobuf::internal::kEmptyString) {
|
||||
delete error_;
|
||||
}
|
||||
if (error) {
|
||||
set_has_error();
|
||||
error_ = error;
|
||||
} else {
|
||||
clear_has_error();
|
||||
error_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
|
||||
}
|
||||
}
|
||||
|
||||
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
|
||||
inline int CodeGeneratorResponse::file_size() const {
|
||||
return file_.size();
|
||||
}
|
||||
inline void CodeGeneratorResponse::clear_file() {
|
||||
file_.Clear();
|
||||
}
|
||||
inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
|
||||
return file_.Get(index);
|
||||
}
|
||||
inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) {
|
||||
return file_.Mutable(index);
|
||||
}
|
||||
inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
|
||||
return file_.Add();
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
|
||||
CodeGeneratorResponse::file() const {
|
||||
return file_;
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
|
||||
CodeGeneratorResponse::mutable_file() {
|
||||
return &file_;
|
||||
}
|
||||
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#ifndef SWIG
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
|
||||
} // namespace google
|
||||
} // namespace protobuf
|
||||
#endif // SWIG
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#endif // PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,484 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// To test GeneratedMessageReflection, we actually let the protocol compiler
|
||||
// generate a full protocol message implementation and then test its
|
||||
// reflection interface. This is much easier and more maintainable than
|
||||
// trying to create our own Message class for GeneratedMessageReflection
|
||||
// to wrap.
|
||||
//
|
||||
// The tests here closely mirror some of the tests in
|
||||
// compiler/cpp/unittest, except using the reflection interface
|
||||
// rather than generated accessors.
|
||||
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/test_util.h>
|
||||
#include <google/protobuf/unittest.pb.h>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/testing/googletest.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace {
|
||||
|
||||
// Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes.
|
||||
const FieldDescriptor* F(const string& name) {
|
||||
const FieldDescriptor* result =
|
||||
unittest::TestAllTypes::descriptor()->FindFieldByName(name);
|
||||
GOOGLE_CHECK(result != NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, Defaults) {
|
||||
// Check that all default values are set correctly in the initial message.
|
||||
unittest::TestAllTypes message;
|
||||
TestUtil::ReflectionTester reflection_tester(
|
||||
unittest::TestAllTypes::descriptor());
|
||||
|
||||
reflection_tester.ExpectClearViaReflection(message);
|
||||
|
||||
const Reflection* reflection = message.GetReflection();
|
||||
|
||||
// Messages should return pointers to default instances until first use.
|
||||
// (This is not checked by ExpectClear() since it is not actually true after
|
||||
// the fields have been set and then cleared.)
|
||||
EXPECT_EQ(&unittest::TestAllTypes::OptionalGroup::default_instance(),
|
||||
&reflection->GetMessage(message, F("optionalgroup")));
|
||||
EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(),
|
||||
&reflection->GetMessage(message, F("optional_nested_message")));
|
||||
EXPECT_EQ(&unittest::ForeignMessage::default_instance(),
|
||||
&reflection->GetMessage(message, F("optional_foreign_message")));
|
||||
EXPECT_EQ(&unittest_import::ImportMessage::default_instance(),
|
||||
&reflection->GetMessage(message, F("optional_import_message")));
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, Accessors) {
|
||||
// Set every field to a unique value then go back and check all those
|
||||
// values.
|
||||
unittest::TestAllTypes message;
|
||||
TestUtil::ReflectionTester reflection_tester(
|
||||
unittest::TestAllTypes::descriptor());
|
||||
|
||||
reflection_tester.SetAllFieldsViaReflection(&message);
|
||||
TestUtil::ExpectAllFieldsSet(message);
|
||||
reflection_tester.ExpectAllFieldsSetViaReflection(message);
|
||||
|
||||
reflection_tester.ModifyRepeatedFieldsViaReflection(&message);
|
||||
TestUtil::ExpectRepeatedFieldsModified(message);
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, GetStringReference) {
|
||||
// Test that GetStringReference() returns the underlying string when it is
|
||||
// a normal string field.
|
||||
unittest::TestAllTypes message;
|
||||
message.set_optional_string("foo");
|
||||
message.add_repeated_string("foo");
|
||||
|
||||
const Reflection* reflection = message.GetReflection();
|
||||
string scratch;
|
||||
|
||||
EXPECT_EQ(&message.optional_string(),
|
||||
&reflection->GetStringReference(message, F("optional_string"), &scratch))
|
||||
<< "For simple string fields, GetStringReference() should return a "
|
||||
"reference to the underlying string.";
|
||||
EXPECT_EQ(&message.repeated_string(0),
|
||||
&reflection->GetRepeatedStringReference(message, F("repeated_string"),
|
||||
0, &scratch))
|
||||
<< "For simple string fields, GetRepeatedStringReference() should return "
|
||||
"a reference to the underlying string.";
|
||||
}
|
||||
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, DefaultsAfterClear) {
|
||||
// Check that after setting all fields and then clearing, getting an
|
||||
// embedded message does NOT return the default instance.
|
||||
unittest::TestAllTypes message;
|
||||
TestUtil::ReflectionTester reflection_tester(
|
||||
unittest::TestAllTypes::descriptor());
|
||||
|
||||
TestUtil::SetAllFields(&message);
|
||||
message.Clear();
|
||||
|
||||
const Reflection* reflection = message.GetReflection();
|
||||
|
||||
EXPECT_NE(&unittest::TestAllTypes::OptionalGroup::default_instance(),
|
||||
&reflection->GetMessage(message, F("optionalgroup")));
|
||||
EXPECT_NE(&unittest::TestAllTypes::NestedMessage::default_instance(),
|
||||
&reflection->GetMessage(message, F("optional_nested_message")));
|
||||
EXPECT_NE(&unittest::ForeignMessage::default_instance(),
|
||||
&reflection->GetMessage(message, F("optional_foreign_message")));
|
||||
EXPECT_NE(&unittest_import::ImportMessage::default_instance(),
|
||||
&reflection->GetMessage(message, F("optional_import_message")));
|
||||
}
|
||||
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, Swap) {
|
||||
unittest::TestAllTypes message1;
|
||||
unittest::TestAllTypes message2;
|
||||
|
||||
TestUtil::SetAllFields(&message1);
|
||||
|
||||
const Reflection* reflection = message1.GetReflection();
|
||||
reflection->Swap(&message1, &message2);
|
||||
|
||||
TestUtil::ExpectClear(message1);
|
||||
TestUtil::ExpectAllFieldsSet(message2);
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, SwapWithBothSet) {
|
||||
unittest::TestAllTypes message1;
|
||||
unittest::TestAllTypes message2;
|
||||
|
||||
TestUtil::SetAllFields(&message1);
|
||||
TestUtil::SetAllFields(&message2);
|
||||
TestUtil::ModifyRepeatedFields(&message2);
|
||||
|
||||
const Reflection* reflection = message1.GetReflection();
|
||||
reflection->Swap(&message1, &message2);
|
||||
|
||||
TestUtil::ExpectRepeatedFieldsModified(message1);
|
||||
TestUtil::ExpectAllFieldsSet(message2);
|
||||
|
||||
message1.set_optional_int32(532819);
|
||||
|
||||
reflection->Swap(&message1, &message2);
|
||||
|
||||
EXPECT_EQ(532819, message2.optional_int32());
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, SwapExtensions) {
|
||||
unittest::TestAllExtensions message1;
|
||||
unittest::TestAllExtensions message2;
|
||||
|
||||
TestUtil::SetAllExtensions(&message1);
|
||||
|
||||
const Reflection* reflection = message1.GetReflection();
|
||||
reflection->Swap(&message1, &message2);
|
||||
|
||||
TestUtil::ExpectExtensionsClear(message1);
|
||||
TestUtil::ExpectAllExtensionsSet(message2);
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, SwapUnknown) {
|
||||
unittest::TestEmptyMessage message1, message2;
|
||||
|
||||
message1.mutable_unknown_fields()->AddVarint(1234, 1);
|
||||
|
||||
EXPECT_EQ(1, message1.unknown_fields().field_count());
|
||||
EXPECT_EQ(0, message2.unknown_fields().field_count());
|
||||
const Reflection* reflection = message1.GetReflection();
|
||||
reflection->Swap(&message1, &message2);
|
||||
EXPECT_EQ(0, message1.unknown_fields().field_count());
|
||||
EXPECT_EQ(1, message2.unknown_fields().field_count());
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, RemoveLast) {
|
||||
unittest::TestAllTypes message;
|
||||
TestUtil::ReflectionTester reflection_tester(
|
||||
unittest::TestAllTypes::descriptor());
|
||||
|
||||
TestUtil::SetAllFields(&message);
|
||||
|
||||
reflection_tester.RemoveLastRepeatedsViaReflection(&message);
|
||||
|
||||
TestUtil::ExpectLastRepeatedsRemoved(message);
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, RemoveLastExtensions) {
|
||||
unittest::TestAllExtensions message;
|
||||
TestUtil::ReflectionTester reflection_tester(
|
||||
unittest::TestAllExtensions::descriptor());
|
||||
|
||||
TestUtil::SetAllExtensions(&message);
|
||||
|
||||
reflection_tester.RemoveLastRepeatedsViaReflection(&message);
|
||||
|
||||
TestUtil::ExpectLastRepeatedExtensionsRemoved(message);
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, ReleaseLast) {
|
||||
unittest::TestAllTypes message;
|
||||
const Descriptor* descriptor = message.GetDescriptor();
|
||||
TestUtil::ReflectionTester reflection_tester(descriptor);
|
||||
|
||||
TestUtil::SetAllFields(&message);
|
||||
|
||||
reflection_tester.ReleaseLastRepeatedsViaReflection(&message, false);
|
||||
|
||||
TestUtil::ExpectLastRepeatedsReleased(message);
|
||||
|
||||
// Now test that we actually release the right message.
|
||||
message.Clear();
|
||||
TestUtil::SetAllFields(&message);
|
||||
ASSERT_EQ(2, message.repeated_foreign_message_size());
|
||||
const protobuf_unittest::ForeignMessage* expected =
|
||||
message.mutable_repeated_foreign_message(1);
|
||||
scoped_ptr<Message> released(message.GetReflection()->ReleaseLast(
|
||||
&message, descriptor->FindFieldByName("repeated_foreign_message")));
|
||||
EXPECT_EQ(expected, released.get());
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, ReleaseLastExtensions) {
|
||||
unittest::TestAllExtensions message;
|
||||
const Descriptor* descriptor = message.GetDescriptor();
|
||||
TestUtil::ReflectionTester reflection_tester(descriptor);
|
||||
|
||||
TestUtil::SetAllExtensions(&message);
|
||||
|
||||
reflection_tester.ReleaseLastRepeatedsViaReflection(&message, true);
|
||||
|
||||
TestUtil::ExpectLastRepeatedExtensionsReleased(message);
|
||||
|
||||
// Now test that we actually release the right message.
|
||||
message.Clear();
|
||||
TestUtil::SetAllExtensions(&message);
|
||||
ASSERT_EQ(2, message.ExtensionSize(
|
||||
unittest::repeated_foreign_message_extension));
|
||||
const protobuf_unittest::ForeignMessage* expected = message.MutableExtension(
|
||||
unittest::repeated_foreign_message_extension, 1);
|
||||
scoped_ptr<Message> released(message.GetReflection()->ReleaseLast(
|
||||
&message, descriptor->file()->FindExtensionByName(
|
||||
"repeated_foreign_message_extension")));
|
||||
EXPECT_EQ(expected, released.get());
|
||||
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, SwapRepeatedElements) {
|
||||
unittest::TestAllTypes message;
|
||||
TestUtil::ReflectionTester reflection_tester(
|
||||
unittest::TestAllTypes::descriptor());
|
||||
|
||||
TestUtil::SetAllFields(&message);
|
||||
|
||||
// Swap and test that fields are all swapped.
|
||||
reflection_tester.SwapRepeatedsViaReflection(&message);
|
||||
TestUtil::ExpectRepeatedsSwapped(message);
|
||||
|
||||
// Swap back and test that fields are all back to original values.
|
||||
reflection_tester.SwapRepeatedsViaReflection(&message);
|
||||
TestUtil::ExpectAllFieldsSet(message);
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, SwapRepeatedElementsExtension) {
|
||||
unittest::TestAllExtensions message;
|
||||
TestUtil::ReflectionTester reflection_tester(
|
||||
unittest::TestAllExtensions::descriptor());
|
||||
|
||||
TestUtil::SetAllExtensions(&message);
|
||||
|
||||
// Swap and test that fields are all swapped.
|
||||
reflection_tester.SwapRepeatedsViaReflection(&message);
|
||||
TestUtil::ExpectRepeatedExtensionsSwapped(message);
|
||||
|
||||
// Swap back and test that fields are all back to original values.
|
||||
reflection_tester.SwapRepeatedsViaReflection(&message);
|
||||
TestUtil::ExpectAllExtensionsSet(message);
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, Extensions) {
|
||||
// Set every extension to a unique value then go back and check all those
|
||||
// values.
|
||||
unittest::TestAllExtensions message;
|
||||
TestUtil::ReflectionTester reflection_tester(
|
||||
unittest::TestAllExtensions::descriptor());
|
||||
|
||||
reflection_tester.SetAllFieldsViaReflection(&message);
|
||||
TestUtil::ExpectAllExtensionsSet(message);
|
||||
reflection_tester.ExpectAllFieldsSetViaReflection(message);
|
||||
|
||||
reflection_tester.ModifyRepeatedFieldsViaReflection(&message);
|
||||
TestUtil::ExpectRepeatedExtensionsModified(message);
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, FindExtensionTypeByNumber) {
|
||||
const Reflection* reflection =
|
||||
unittest::TestAllExtensions::default_instance().GetReflection();
|
||||
|
||||
const FieldDescriptor* extension1 =
|
||||
unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName(
|
||||
"optional_int32_extension");
|
||||
const FieldDescriptor* extension2 =
|
||||
unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName(
|
||||
"repeated_string_extension");
|
||||
|
||||
EXPECT_EQ(extension1,
|
||||
reflection->FindKnownExtensionByNumber(extension1->number()));
|
||||
EXPECT_EQ(extension2,
|
||||
reflection->FindKnownExtensionByNumber(extension2->number()));
|
||||
|
||||
// Non-existent extension.
|
||||
EXPECT_TRUE(reflection->FindKnownExtensionByNumber(62341) == NULL);
|
||||
|
||||
// Extensions of TestAllExtensions should not show up as extensions of
|
||||
// other types.
|
||||
EXPECT_TRUE(unittest::TestAllTypes::default_instance().GetReflection()->
|
||||
FindKnownExtensionByNumber(extension1->number()) == NULL);
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, FindKnownExtensionByName) {
|
||||
const Reflection* reflection =
|
||||
unittest::TestAllExtensions::default_instance().GetReflection();
|
||||
|
||||
const FieldDescriptor* extension1 =
|
||||
unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName(
|
||||
"optional_int32_extension");
|
||||
const FieldDescriptor* extension2 =
|
||||
unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName(
|
||||
"repeated_string_extension");
|
||||
|
||||
EXPECT_EQ(extension1,
|
||||
reflection->FindKnownExtensionByName(extension1->full_name()));
|
||||
EXPECT_EQ(extension2,
|
||||
reflection->FindKnownExtensionByName(extension2->full_name()));
|
||||
|
||||
// Non-existent extension.
|
||||
EXPECT_TRUE(reflection->FindKnownExtensionByName("no_such_ext") == NULL);
|
||||
|
||||
// Extensions of TestAllExtensions should not show up as extensions of
|
||||
// other types.
|
||||
EXPECT_TRUE(unittest::TestAllTypes::default_instance().GetReflection()->
|
||||
FindKnownExtensionByName(extension1->full_name()) == NULL);
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, ReleaseMessageTest) {
|
||||
unittest::TestAllTypes message;
|
||||
TestUtil::ReflectionTester reflection_tester(
|
||||
unittest::TestAllTypes::descriptor());
|
||||
|
||||
// When nothing is set, we expect all released messages to be NULL.
|
||||
reflection_tester.ExpectMessagesReleasedViaReflection(
|
||||
&message, TestUtil::ReflectionTester::IS_NULL);
|
||||
|
||||
// After fields are set we should get non-NULL releases.
|
||||
reflection_tester.SetAllFieldsViaReflection(&message);
|
||||
reflection_tester.ExpectMessagesReleasedViaReflection(
|
||||
&message, TestUtil::ReflectionTester::NOT_NULL);
|
||||
|
||||
// After Clear() we may or may not get a message from ReleaseMessage().
|
||||
// This is implementation specific.
|
||||
reflection_tester.SetAllFieldsViaReflection(&message);
|
||||
message.Clear();
|
||||
reflection_tester.ExpectMessagesReleasedViaReflection(
|
||||
&message, TestUtil::ReflectionTester::CAN_BE_NULL);
|
||||
|
||||
// Test a different code path for setting after releasing.
|
||||
TestUtil::SetAllFields(&message);
|
||||
TestUtil::ExpectAllFieldsSet(message);
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, ReleaseExtensionMessageTest) {
|
||||
unittest::TestAllExtensions message;
|
||||
TestUtil::ReflectionTester reflection_tester(
|
||||
unittest::TestAllExtensions::descriptor());
|
||||
|
||||
// When nothing is set, we expect all released messages to be NULL.
|
||||
reflection_tester.ExpectMessagesReleasedViaReflection(
|
||||
&message, TestUtil::ReflectionTester::IS_NULL);
|
||||
|
||||
// After fields are set we should get non-NULL releases.
|
||||
reflection_tester.SetAllFieldsViaReflection(&message);
|
||||
reflection_tester.ExpectMessagesReleasedViaReflection(
|
||||
&message, TestUtil::ReflectionTester::NOT_NULL);
|
||||
|
||||
// After Clear() we may or may not get a message from ReleaseMessage().
|
||||
// This is implementation specific.
|
||||
reflection_tester.SetAllFieldsViaReflection(&message);
|
||||
message.Clear();
|
||||
reflection_tester.ExpectMessagesReleasedViaReflection(
|
||||
&message, TestUtil::ReflectionTester::CAN_BE_NULL);
|
||||
|
||||
// Test a different code path for setting after releasing.
|
||||
TestUtil::SetAllExtensions(&message);
|
||||
TestUtil::ExpectAllExtensionsSet(message);
|
||||
}
|
||||
|
||||
#ifdef PROTOBUF_HAS_DEATH_TEST
|
||||
|
||||
TEST(GeneratedMessageReflectionTest, UsageErrors) {
|
||||
unittest::TestAllTypes message;
|
||||
const Reflection* reflection = message.GetReflection();
|
||||
const Descriptor* descriptor = message.GetDescriptor();
|
||||
|
||||
#define f(NAME) descriptor->FindFieldByName(NAME)
|
||||
|
||||
// Testing every single failure mode would be too much work. Let's just
|
||||
// check a few.
|
||||
EXPECT_DEATH(
|
||||
reflection->GetInt32(
|
||||
message, descriptor->FindFieldByName("optional_int64")),
|
||||
"Protocol Buffer reflection usage error:\n"
|
||||
" Method : google::protobuf::Reflection::GetInt32\n"
|
||||
" Message type: protobuf_unittest\\.TestAllTypes\n"
|
||||
" Field : protobuf_unittest\\.TestAllTypes\\.optional_int64\n"
|
||||
" Problem : Field is not the right type for this message:\n"
|
||||
" Expected : CPPTYPE_INT32\n"
|
||||
" Field type: CPPTYPE_INT64");
|
||||
EXPECT_DEATH(
|
||||
reflection->GetInt32(
|
||||
message, descriptor->FindFieldByName("repeated_int32")),
|
||||
"Protocol Buffer reflection usage error:\n"
|
||||
" Method : google::protobuf::Reflection::GetInt32\n"
|
||||
" Message type: protobuf_unittest.TestAllTypes\n"
|
||||
" Field : protobuf_unittest.TestAllTypes.repeated_int32\n"
|
||||
" Problem : Field is repeated; the method requires a singular field.");
|
||||
EXPECT_DEATH(
|
||||
reflection->GetInt32(
|
||||
message, unittest::ForeignMessage::descriptor()->FindFieldByName("c")),
|
||||
"Protocol Buffer reflection usage error:\n"
|
||||
" Method : google::protobuf::Reflection::GetInt32\n"
|
||||
" Message type: protobuf_unittest.TestAllTypes\n"
|
||||
" Field : protobuf_unittest.ForeignMessage.c\n"
|
||||
" Problem : Field does not match message type.");
|
||||
EXPECT_DEATH(
|
||||
reflection->HasField(
|
||||
message, unittest::ForeignMessage::descriptor()->FindFieldByName("c")),
|
||||
"Protocol Buffer reflection usage error:\n"
|
||||
" Method : google::protobuf::Reflection::HasField\n"
|
||||
" Message type: protobuf_unittest.TestAllTypes\n"
|
||||
" Field : protobuf_unittest.ForeignMessage.c\n"
|
||||
" Problem : Field does not match message type.");
|
||||
|
||||
#undef f
|
||||
}
|
||||
|
||||
#endif // PROTOBUF_HAS_DEATH_TEST
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -1,198 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter)
|
||||
: variable_delimiter_(variable_delimiter),
|
||||
output_(output),
|
||||
buffer_(NULL),
|
||||
buffer_size_(0),
|
||||
at_start_of_line_(true),
|
||||
failed_(false) {
|
||||
}
|
||||
|
||||
Printer::~Printer() {
|
||||
// Only BackUp() if we have called Next() at least once and never failed.
|
||||
if (buffer_size_ > 0 && !failed_) {
|
||||
output_->BackUp(buffer_size_);
|
||||
}
|
||||
}
|
||||
|
||||
void Printer::Print(const map<string, string>& variables, const char* text) {
|
||||
int size = strlen(text);
|
||||
int pos = 0; // The number of bytes we've written so far.
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (text[i] == '\n') {
|
||||
// Saw newline. If there is more text, we may need to insert an indent
|
||||
// here. So, write what we have so far, including the '\n'.
|
||||
WriteRaw(text + pos, i - pos + 1);
|
||||
pos = i + 1;
|
||||
|
||||
// Setting this true will cause the next WriteRaw() to insert an indent
|
||||
// first.
|
||||
at_start_of_line_ = true;
|
||||
|
||||
} else if (text[i] == variable_delimiter_) {
|
||||
// Saw the start of a variable name.
|
||||
|
||||
// Write what we have so far.
|
||||
WriteRaw(text + pos, i - pos);
|
||||
pos = i + 1;
|
||||
|
||||
// Find closing delimiter.
|
||||
const char* end = strchr(text + pos, variable_delimiter_);
|
||||
if (end == NULL) {
|
||||
GOOGLE_LOG(DFATAL) << " Unclosed variable name.";
|
||||
end = text + pos;
|
||||
}
|
||||
int endpos = end - text;
|
||||
|
||||
string varname(text + pos, endpos - pos);
|
||||
if (varname.empty()) {
|
||||
// Two delimiters in a row reduce to a literal delimiter character.
|
||||
WriteRaw(&variable_delimiter_, 1);
|
||||
} else {
|
||||
// Replace with the variable's value.
|
||||
map<string, string>::const_iterator iter = variables.find(varname);
|
||||
if (iter == variables.end()) {
|
||||
GOOGLE_LOG(DFATAL) << " Undefined variable: " << varname;
|
||||
} else {
|
||||
WriteRaw(iter->second.data(), iter->second.size());
|
||||
}
|
||||
}
|
||||
|
||||
// Advance past this variable.
|
||||
i = endpos;
|
||||
pos = endpos + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Write the rest.
|
||||
WriteRaw(text + pos, size - pos);
|
||||
}
|
||||
|
||||
void Printer::Print(const char* text) {
|
||||
static map<string, string> empty;
|
||||
Print(empty, text);
|
||||
}
|
||||
|
||||
void Printer::Print(const char* text,
|
||||
const char* variable, const string& value) {
|
||||
map<string, string> vars;
|
||||
vars[variable] = value;
|
||||
Print(vars, text);
|
||||
}
|
||||
|
||||
void Printer::Print(const char* text,
|
||||
const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2) {
|
||||
map<string, string> vars;
|
||||
vars[variable1] = value1;
|
||||
vars[variable2] = value2;
|
||||
Print(vars, text);
|
||||
}
|
||||
|
||||
void Printer::Print(const char* text,
|
||||
const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2,
|
||||
const char* variable3, const string& value3) {
|
||||
map<string, string> vars;
|
||||
vars[variable1] = value1;
|
||||
vars[variable2] = value2;
|
||||
vars[variable3] = value3;
|
||||
Print(vars, text);
|
||||
}
|
||||
|
||||
void Printer::Indent() {
|
||||
indent_ += " ";
|
||||
}
|
||||
|
||||
void Printer::Outdent() {
|
||||
if (indent_.empty()) {
|
||||
GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent().";
|
||||
return;
|
||||
}
|
||||
|
||||
indent_.resize(indent_.size() - 2);
|
||||
}
|
||||
|
||||
void Printer::PrintRaw(const string& data) {
|
||||
WriteRaw(data.data(), data.size());
|
||||
}
|
||||
|
||||
void Printer::PrintRaw(const char* data) {
|
||||
if (failed_) return;
|
||||
WriteRaw(data, strlen(data));
|
||||
}
|
||||
|
||||
void Printer::WriteRaw(const char* data, int size) {
|
||||
if (failed_) return;
|
||||
if (size == 0) return;
|
||||
|
||||
if (at_start_of_line_ && (size > 0) && (data[0] != '\n')) {
|
||||
// Insert an indent.
|
||||
at_start_of_line_ = false;
|
||||
WriteRaw(indent_.data(), indent_.size());
|
||||
if (failed_) return;
|
||||
}
|
||||
|
||||
while (size > buffer_size_) {
|
||||
// Data exceeds space in the buffer. Copy what we can and request a
|
||||
// new buffer.
|
||||
memcpy(buffer_, data, buffer_size_);
|
||||
data += buffer_size_;
|
||||
size -= buffer_size_;
|
||||
void* void_buffer;
|
||||
failed_ = !output_->Next(&void_buffer, &buffer_size_);
|
||||
if (failed_) return;
|
||||
buffer_ = reinterpret_cast<char*>(void_buffer);
|
||||
}
|
||||
|
||||
// Buffer is big enough to receive the data; copy it.
|
||||
memcpy(buffer_, data, size);
|
||||
buffer_ += size;
|
||||
buffer_size_ -= size;
|
||||
}
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -1,136 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Utility class for writing text to a ZeroCopyOutputStream.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_PRINTER_H__
|
||||
#define GOOGLE_PROTOBUF_IO_PRINTER_H__
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
class ZeroCopyOutputStream; // zero_copy_stream.h
|
||||
|
||||
// This simple utility class assists in code generation. It basically
|
||||
// allows the caller to define a set of variables and then output some
|
||||
// text with variable substitutions. Example usage:
|
||||
//
|
||||
// Printer printer(output, '$');
|
||||
// map<string, string> vars;
|
||||
// vars["name"] = "Bob";
|
||||
// printer.Print(vars, "My name is $name$.");
|
||||
//
|
||||
// The above writes "My name is Bob." to the output stream.
|
||||
//
|
||||
// Printer aggressively enforces correct usage, crashing (with assert failures)
|
||||
// in the case of undefined variables in debug builds. This helps greatly in
|
||||
// debugging code which uses it.
|
||||
class LIBPROTOBUF_EXPORT Printer {
|
||||
public:
|
||||
// Create a printer that writes text to the given output stream. Use the
|
||||
// given character as the delimiter for variables.
|
||||
Printer(ZeroCopyOutputStream* output, char variable_delimiter);
|
||||
~Printer();
|
||||
|
||||
// Print some text after applying variable substitutions. If a particular
|
||||
// variable in the text is not defined, this will crash. Variables to be
|
||||
// substituted are identified by their names surrounded by delimiter
|
||||
// characters (as given to the constructor). The variable bindings are
|
||||
// defined by the given map.
|
||||
void Print(const map<string, string>& variables, const char* text);
|
||||
|
||||
// Like the first Print(), except the substitutions are given as parameters.
|
||||
void Print(const char* text);
|
||||
// Like the first Print(), except the substitutions are given as parameters.
|
||||
void Print(const char* text, const char* variable, const string& value);
|
||||
// Like the first Print(), except the substitutions are given as parameters.
|
||||
void Print(const char* text, const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2);
|
||||
// Like the first Print(), except the substitutions are given as parameters.
|
||||
void Print(const char* text, const char* variable1, const string& value1,
|
||||
const char* variable2, const string& value2,
|
||||
const char* variable3, const string& value3);
|
||||
// TODO(kenton): Overloaded versions with more variables? Three seems
|
||||
// to be enough.
|
||||
|
||||
// Indent text by two spaces. After calling Indent(), two spaces will be
|
||||
// inserted at the beginning of each line of text. Indent() may be called
|
||||
// multiple times to produce deeper indents.
|
||||
void Indent();
|
||||
|
||||
// Reduces the current indent level by two spaces, or crashes if the indent
|
||||
// level is zero.
|
||||
void Outdent();
|
||||
|
||||
// Write a string to the output buffer.
|
||||
// This method does not look for newlines to add indentation.
|
||||
void PrintRaw(const string& data);
|
||||
|
||||
// Write a zero-delimited string to output buffer.
|
||||
// This method does not look for newlines to add indentation.
|
||||
void PrintRaw(const char* data);
|
||||
|
||||
// Write some bytes to the output buffer.
|
||||
// This method does not look for newlines to add indentation.
|
||||
void WriteRaw(const char* data, int size);
|
||||
|
||||
// True if any write to the underlying stream failed. (We don't just
|
||||
// crash in this case because this is an I/O failure, not a programming
|
||||
// error.)
|
||||
bool failed() const { return failed_; }
|
||||
|
||||
private:
|
||||
const char variable_delimiter_;
|
||||
|
||||
ZeroCopyOutputStream* const output_;
|
||||
char* buffer_;
|
||||
int buffer_size_;
|
||||
|
||||
string indent_;
|
||||
bool at_start_of_line_;
|
||||
bool failed_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Printer);
|
||||
};
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_IO_PRINTER_H__
|
||||
@@ -1,185 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/test_util_lite.h>
|
||||
#include <google/protobuf/unittest_lite.pb.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace {
|
||||
// Helper methods to test parsing merge behavior.
|
||||
void ExpectMessageMerged(const google::protobuf::unittest::TestAllTypesLite& message) {
|
||||
GOOGLE_CHECK(message.optional_int32() == 3);
|
||||
GOOGLE_CHECK(message.optional_int64() == 2);
|
||||
GOOGLE_CHECK(message.optional_string() == "hello");
|
||||
}
|
||||
|
||||
void AssignParsingMergeMessages(
|
||||
google::protobuf::unittest::TestAllTypesLite* msg1,
|
||||
google::protobuf::unittest::TestAllTypesLite* msg2,
|
||||
google::protobuf::unittest::TestAllTypesLite* msg3) {
|
||||
msg1->set_optional_int32(1);
|
||||
msg2->set_optional_int64(2);
|
||||
msg3->set_optional_int32(3);
|
||||
msg3->set_optional_string("hello");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
string data, packed_data;
|
||||
|
||||
{
|
||||
protobuf_unittest::TestAllTypesLite message, message2, message3;
|
||||
google::protobuf::TestUtilLite::ExpectClear(message);
|
||||
google::protobuf::TestUtilLite::SetAllFields(&message);
|
||||
message2.CopyFrom(message);
|
||||
data = message.SerializeAsString();
|
||||
message3.ParseFromString(data);
|
||||
google::protobuf::TestUtilLite::ExpectAllFieldsSet(message);
|
||||
google::protobuf::TestUtilLite::ExpectAllFieldsSet(message2);
|
||||
google::protobuf::TestUtilLite::ExpectAllFieldsSet(message3);
|
||||
google::protobuf::TestUtilLite::ModifyRepeatedFields(&message);
|
||||
google::protobuf::TestUtilLite::ExpectRepeatedFieldsModified(message);
|
||||
message.Clear();
|
||||
google::protobuf::TestUtilLite::ExpectClear(message);
|
||||
}
|
||||
|
||||
{
|
||||
protobuf_unittest::TestAllExtensionsLite message, message2, message3;
|
||||
google::protobuf::TestUtilLite::ExpectExtensionsClear(message);
|
||||
google::protobuf::TestUtilLite::SetAllExtensions(&message);
|
||||
message2.CopyFrom(message);
|
||||
string extensions_data = message.SerializeAsString();
|
||||
GOOGLE_CHECK(extensions_data == data);
|
||||
message3.ParseFromString(extensions_data);
|
||||
google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message);
|
||||
google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message2);
|
||||
google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message3);
|
||||
google::protobuf::TestUtilLite::ModifyRepeatedExtensions(&message);
|
||||
google::protobuf::TestUtilLite::ExpectRepeatedExtensionsModified(message);
|
||||
message.Clear();
|
||||
google::protobuf::TestUtilLite::ExpectExtensionsClear(message);
|
||||
}
|
||||
|
||||
{
|
||||
protobuf_unittest::TestPackedTypesLite message, message2, message3;
|
||||
google::protobuf::TestUtilLite::ExpectPackedClear(message);
|
||||
google::protobuf::TestUtilLite::SetPackedFields(&message);
|
||||
message2.CopyFrom(message);
|
||||
packed_data = message.SerializeAsString();
|
||||
message3.ParseFromString(packed_data);
|
||||
google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message);
|
||||
google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message2);
|
||||
google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message3);
|
||||
google::protobuf::TestUtilLite::ModifyPackedFields(&message);
|
||||
google::protobuf::TestUtilLite::ExpectPackedFieldsModified(message);
|
||||
message.Clear();
|
||||
google::protobuf::TestUtilLite::ExpectPackedClear(message);
|
||||
}
|
||||
|
||||
{
|
||||
protobuf_unittest::TestPackedExtensionsLite message, message2, message3;
|
||||
google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message);
|
||||
google::protobuf::TestUtilLite::SetPackedExtensions(&message);
|
||||
message2.CopyFrom(message);
|
||||
string packed_extensions_data = message.SerializeAsString();
|
||||
GOOGLE_CHECK(packed_extensions_data == packed_data);
|
||||
message3.ParseFromString(packed_extensions_data);
|
||||
google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message);
|
||||
google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message2);
|
||||
google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message3);
|
||||
google::protobuf::TestUtilLite::ModifyPackedExtensions(&message);
|
||||
google::protobuf::TestUtilLite::ExpectPackedExtensionsModified(message);
|
||||
message.Clear();
|
||||
google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message);
|
||||
}
|
||||
|
||||
{
|
||||
// Test that if an optional or required message/group field appears multiple
|
||||
// times in the input, they need to be merged.
|
||||
google::protobuf::unittest::TestParsingMergeLite::RepeatedFieldsGenerator generator;
|
||||
google::protobuf::unittest::TestAllTypesLite* msg1;
|
||||
google::protobuf::unittest::TestAllTypesLite* msg2;
|
||||
google::protobuf::unittest::TestAllTypesLite* msg3;
|
||||
|
||||
#define ASSIGN_REPEATED_FIELD(FIELD) \
|
||||
msg1 = generator.add_##FIELD(); \
|
||||
msg2 = generator.add_##FIELD(); \
|
||||
msg3 = generator.add_##FIELD(); \
|
||||
AssignParsingMergeMessages(msg1, msg2, msg3)
|
||||
|
||||
ASSIGN_REPEATED_FIELD(field1);
|
||||
ASSIGN_REPEATED_FIELD(field2);
|
||||
ASSIGN_REPEATED_FIELD(field3);
|
||||
ASSIGN_REPEATED_FIELD(ext1);
|
||||
ASSIGN_REPEATED_FIELD(ext2);
|
||||
|
||||
#undef ASSIGN_REPEATED_FIELD
|
||||
#define ASSIGN_REPEATED_GROUP(FIELD) \
|
||||
msg1 = generator.add_##FIELD()->mutable_field1(); \
|
||||
msg2 = generator.add_##FIELD()->mutable_field1(); \
|
||||
msg3 = generator.add_##FIELD()->mutable_field1(); \
|
||||
AssignParsingMergeMessages(msg1, msg2, msg3)
|
||||
|
||||
ASSIGN_REPEATED_GROUP(group1);
|
||||
ASSIGN_REPEATED_GROUP(group2);
|
||||
|
||||
#undef ASSIGN_REPEATED_GROUP
|
||||
|
||||
string buffer;
|
||||
generator.SerializeToString(&buffer);
|
||||
google::protobuf::unittest::TestParsingMergeLite parsing_merge;
|
||||
parsing_merge.ParseFromString(buffer);
|
||||
|
||||
// Required and optional fields should be merged.
|
||||
ExpectMessageMerged(parsing_merge.required_all_types());
|
||||
ExpectMessageMerged(parsing_merge.optional_all_types());
|
||||
ExpectMessageMerged(
|
||||
parsing_merge.optionalgroup().optional_group_all_types());
|
||||
ExpectMessageMerged(parsing_merge.GetExtension(
|
||||
google::protobuf::unittest::TestParsingMergeLite::optional_ext));
|
||||
|
||||
// Repeated fields should not be merged.
|
||||
GOOGLE_CHECK(parsing_merge.repeated_all_types_size() == 3);
|
||||
GOOGLE_CHECK(parsing_merge.repeatedgroup_size() == 3);
|
||||
GOOGLE_CHECK(parsing_merge.ExtensionSize(
|
||||
google::protobuf::unittest::TestParsingMergeLite::repeated_ext) == 3);
|
||||
}
|
||||
|
||||
cout << "PASS" << endl;
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,195 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Author: tgs@google.com (Tom Szymanski)
|
||||
//
|
||||
// Test reflection methods for aggregate access to Repeated[Ptr]Fields.
|
||||
// This test proto2 methods on a proto2 layout.
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/stringprintf.h>
|
||||
#include <google/protobuf/unittest.pb.h>
|
||||
#include <google/protobuf/test_util.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
using unittest::ForeignMessage;
|
||||
using unittest::TestAllTypes;
|
||||
using unittest::TestAllExtensions;
|
||||
|
||||
namespace {
|
||||
|
||||
static int Func(int i, int j) {
|
||||
return i * j;
|
||||
}
|
||||
|
||||
static string StrFunc(int i, int j) {
|
||||
string str;
|
||||
SStringPrintf(&str, "%d", Func(i, 4));
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
TEST(RepeatedFieldReflectionTest, RegularFields) {
|
||||
TestAllTypes message;
|
||||
const Reflection* refl = message.GetReflection();
|
||||
const Descriptor* desc = message.GetDescriptor();
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
message.add_repeated_int32(Func(i, 1));
|
||||
message.add_repeated_double(Func(i, 2));
|
||||
message.add_repeated_string(StrFunc(i, 5));
|
||||
message.add_repeated_foreign_message()->set_c(Func(i, 6));
|
||||
}
|
||||
|
||||
// Get FieldDescriptors for all the fields of interest.
|
||||
const FieldDescriptor* fd_repeated_int32 =
|
||||
desc->FindFieldByName("repeated_int32");
|
||||
const FieldDescriptor* fd_repeated_double =
|
||||
desc->FindFieldByName("repeated_double");
|
||||
const FieldDescriptor* fd_repeated_string =
|
||||
desc->FindFieldByName("repeated_string");
|
||||
const FieldDescriptor* fd_repeated_foreign_message =
|
||||
desc->FindFieldByName("repeated_foreign_message");
|
||||
|
||||
// Get RepeatedField objects for all fields of interest.
|
||||
const RepeatedField<int32>& rf_int32 =
|
||||
refl->GetRepeatedField<int32>(message, fd_repeated_int32);
|
||||
const RepeatedField<double>& rf_double =
|
||||
refl->GetRepeatedField<double>(message, fd_repeated_double);
|
||||
|
||||
// Get mutable RepeatedField objects for all fields of interest.
|
||||
RepeatedField<int32>* mrf_int32 =
|
||||
refl->MutableRepeatedField<int32>(&message, fd_repeated_int32);
|
||||
RepeatedField<double>* mrf_double =
|
||||
refl->MutableRepeatedField<double>(&message, fd_repeated_double);
|
||||
|
||||
// Get RepeatedPtrField objects for all fields of interest.
|
||||
const RepeatedPtrField<string>& rpf_string =
|
||||
refl->GetRepeatedPtrField<string>(message, fd_repeated_string);
|
||||
const RepeatedPtrField<ForeignMessage>& rpf_foreign_message =
|
||||
refl->GetRepeatedPtrField<ForeignMessage>(
|
||||
message, fd_repeated_foreign_message);
|
||||
const RepeatedPtrField<Message>& rpf_message =
|
||||
refl->GetRepeatedPtrField<Message>(
|
||||
message, fd_repeated_foreign_message);
|
||||
|
||||
// Get mutable RepeatedPtrField objects for all fields of interest.
|
||||
RepeatedPtrField<string>* mrpf_string =
|
||||
refl->MutableRepeatedPtrField<string>(&message, fd_repeated_string);
|
||||
RepeatedPtrField<ForeignMessage>* mrpf_foreign_message =
|
||||
refl->MutableRepeatedPtrField<ForeignMessage>(
|
||||
&message, fd_repeated_foreign_message);
|
||||
RepeatedPtrField<Message>* mrpf_message =
|
||||
refl->MutableRepeatedPtrField<Message>(
|
||||
&message, fd_repeated_foreign_message);
|
||||
|
||||
// Make sure we can do get and sets through the Repeated[Ptr]Field objects.
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// Check gets through const objects.
|
||||
EXPECT_EQ(rf_int32.Get(i), Func(i, 1));
|
||||
EXPECT_EQ(rf_double.Get(i), Func(i, 2));
|
||||
EXPECT_EQ(rpf_string.Get(i), StrFunc(i, 5));
|
||||
EXPECT_EQ(rpf_foreign_message.Get(i).c(), Func(i, 6));
|
||||
EXPECT_EQ(down_cast<const ForeignMessage*>(&rpf_message.Get(i))->c(),
|
||||
Func(i, 6));
|
||||
|
||||
// Check gets through mutable objects.
|
||||
EXPECT_EQ(mrf_int32->Get(i), Func(i, 1));
|
||||
EXPECT_EQ(mrf_double->Get(i), Func(i, 2));
|
||||
EXPECT_EQ(mrpf_string->Get(i), StrFunc(i, 5));
|
||||
EXPECT_EQ(mrpf_foreign_message->Get(i).c(), Func(i, 6));
|
||||
EXPECT_EQ(down_cast<const ForeignMessage*>(&mrpf_message->Get(i))->c(),
|
||||
Func(i, 6));
|
||||
|
||||
// Check sets through mutable objects.
|
||||
mrf_int32->Set(i, Func(i, -1));
|
||||
mrf_double->Set(i, Func(i, -2));
|
||||
mrpf_string->Mutable(i)->assign(StrFunc(i, -5));
|
||||
mrpf_foreign_message->Mutable(i)->set_c(Func(i, -6));
|
||||
EXPECT_EQ(message.repeated_int32(i), Func(i, -1));
|
||||
EXPECT_EQ(message.repeated_double(i), Func(i, -2));
|
||||
EXPECT_EQ(message.repeated_string(i), StrFunc(i, -5));
|
||||
EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, -6));
|
||||
down_cast<ForeignMessage*>(mrpf_message->Mutable(i))->set_c(Func(i, 7));
|
||||
EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, 7));
|
||||
}
|
||||
|
||||
#ifdef PROTOBUF_HAS_DEATH_TEST
|
||||
// Make sure types are checked correctly at runtime.
|
||||
const FieldDescriptor* fd_optional_int32 =
|
||||
desc->FindFieldByName("optional_int32");
|
||||
EXPECT_DEATH(refl->GetRepeatedField<int32>(
|
||||
message, fd_optional_int32), "requires a repeated field");
|
||||
EXPECT_DEATH(refl->GetRepeatedField<double>(
|
||||
message, fd_repeated_int32), "not the right type");
|
||||
EXPECT_DEATH(refl->GetRepeatedPtrField<TestAllTypes>(
|
||||
message, fd_repeated_foreign_message), "wrong submessage type");
|
||||
#endif // PROTOBUF_HAS_DEATH_TEST
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
TEST(RepeatedFieldReflectionTest, ExtensionFields) {
|
||||
TestAllExtensions extended_message;
|
||||
const Reflection* refl = extended_message.GetReflection();
|
||||
const Descriptor* desc = extended_message.GetDescriptor();
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
extended_message.AddExtension(
|
||||
unittest::repeated_int64_extension, Func(i, 1));
|
||||
}
|
||||
|
||||
const FieldDescriptor* fd_repeated_int64_extension =
|
||||
desc->file()->FindExtensionByName("repeated_int64_extension");
|
||||
GOOGLE_CHECK(fd_repeated_int64_extension != NULL);
|
||||
|
||||
const RepeatedField<int64>& rf_int64_extension =
|
||||
refl->GetRepeatedField<int64>(extended_message,
|
||||
fd_repeated_int64_extension);
|
||||
|
||||
RepeatedField<int64>* mrf_int64_extension =
|
||||
refl->MutableRepeatedField<int64>(&extended_message,
|
||||
fd_repeated_int64_extension);
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
EXPECT_EQ(Func(i, 1), rf_int64_extension.Get(i));
|
||||
mrf_int64_extension->Set(i, Func(i, -1));
|
||||
EXPECT_EQ(Func(i, -1),
|
||||
extended_message.GetExtension(unittest::repeated_int64_extension, i));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,232 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
//
|
||||
// Deals with the fact that hash_map is not defined everywhere.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_HASH_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_HASH_H__
|
||||
|
||||
#include <string.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include "config.h"
|
||||
|
||||
#if defined(HAVE_HASH_MAP) && defined(HAVE_HASH_SET)
|
||||
#include HASH_MAP_H
|
||||
#include HASH_SET_H
|
||||
#else
|
||||
#define MISSING_HASH
|
||||
#include <map>
|
||||
#include <set>
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
#ifdef MISSING_HASH
|
||||
|
||||
// This system doesn't have hash_map or hash_set. Emulate them using map and
|
||||
// set.
|
||||
|
||||
// Make hash<T> be the same as less<T>. Note that everywhere where custom
|
||||
// hash functions are defined in the protobuf code, they are also defined such
|
||||
// that they can be used as "less" functions, which is required by MSVC anyway.
|
||||
template <typename Key>
|
||||
struct hash {
|
||||
// Dummy, just to make derivative hash functions compile.
|
||||
int operator()(const Key& key) {
|
||||
GOOGLE_LOG(FATAL) << "Should never be called.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool operator()(const Key& a, const Key& b) const {
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
|
||||
// Make sure char* is compared by value.
|
||||
template <>
|
||||
struct hash<const char*> {
|
||||
// Dummy, just to make derivative hash functions compile.
|
||||
int operator()(const char* key) {
|
||||
GOOGLE_LOG(FATAL) << "Should never be called.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool operator()(const char* a, const char* b) const {
|
||||
return strcmp(a, b) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Key, typename Data,
|
||||
typename HashFcn = hash<Key>,
|
||||
typename EqualKey = int >
|
||||
class hash_map : public std::map<Key, Data, HashFcn> {
|
||||
public:
|
||||
hash_map(int = 0) {}
|
||||
};
|
||||
|
||||
template <typename Key,
|
||||
typename HashFcn = hash<Key>,
|
||||
typename EqualKey = int >
|
||||
class hash_set : public std::set<Key, HashFcn> {
|
||||
public:
|
||||
hash_set(int = 0) {}
|
||||
};
|
||||
|
||||
#elif defined(_MSC_VER) && !defined(_STLPORT_VERSION)
|
||||
|
||||
template <typename Key>
|
||||
struct hash : public HASH_NAMESPACE::hash_compare<Key> {
|
||||
};
|
||||
|
||||
// MSVC's hash_compare<const char*> hashes based on the string contents but
|
||||
// compares based on the string pointer. WTF?
|
||||
class CstringLess {
|
||||
public:
|
||||
inline bool operator()(const char* a, const char* b) const {
|
||||
return strcmp(a, b) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<const char*>
|
||||
: public 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> {
|
||||
public:
|
||||
hash_map(int = 0) {}
|
||||
};
|
||||
|
||||
template <typename Key,
|
||||
typename HashFcn = hash<Key>,
|
||||
typename EqualKey = int >
|
||||
class hash_set : public HASH_NAMESPACE::hash_set<
|
||||
Key, HashFcn> {
|
||||
public:
|
||||
hash_set(int = 0) {}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template <typename Key>
|
||||
struct hash : public HASH_NAMESPACE::hash<Key> {
|
||||
};
|
||||
|
||||
template <typename Key>
|
||||
struct hash<const Key*> {
|
||||
inline size_t operator()(const Key* key) const {
|
||||
return reinterpret_cast<size_t>(key);
|
||||
}
|
||||
};
|
||||
|
||||
// Unlike the old SGI version, the TR1 "hash" does not special-case char*. So,
|
||||
// we go ahead and provide our own implementation.
|
||||
template <>
|
||||
struct hash<const char*> {
|
||||
inline size_t operator()(const char* str) const {
|
||||
size_t result = 0;
|
||||
for (; *str != '\0'; str++) {
|
||||
result = 5 * result + *str;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
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> {
|
||||
public:
|
||||
hash_map(int = 0) {}
|
||||
};
|
||||
|
||||
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> {
|
||||
public:
|
||||
hash_set(int = 0) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template <>
|
||||
struct hash<string> {
|
||||
inline size_t operator()(const string& key) const {
|
||||
return hash<const char*>()(key.c_str());
|
||||
}
|
||||
|
||||
static const size_t bucket_size = 4;
|
||||
static const size_t min_buckets = 8;
|
||||
inline size_t operator()(const string& a, const string& b) const {
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename First, typename Second>
|
||||
struct hash<pair<First, Second> > {
|
||||
inline size_t operator()(const pair<First, Second>& key) const {
|
||||
size_t first_hash = hash<First>()(key.first);
|
||||
size_t second_hash = hash<Second>()(key.second);
|
||||
|
||||
// FIXME(kenton): What is the best way to compute this hash? I have
|
||||
// no idea! This seems a bit better than an XOR.
|
||||
return first_hash * ((1 << 16) - 1) + second_hash;
|
||||
}
|
||||
|
||||
static const size_t bucket_size = 4;
|
||||
static const size_t min_buckets = 8;
|
||||
inline size_t operator()(const pair<First, Second>& a,
|
||||
const pair<First, Second>& b) const {
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
|
||||
// Used by GCC/SGI STL only. (Why isn't this provided by the standard
|
||||
// library? :( )
|
||||
struct streq {
|
||||
inline bool operator()(const char* a, const char* b) const {
|
||||
return strcmp(a, b) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_HASH_H__
|
||||
@@ -1,143 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// from google3/util/gtl/map-util.h
|
||||
// Author: Anton Carver
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Perform a lookup in a map or hash_map.
|
||||
// If the key is present in the map then the value associated with that
|
||||
// key is returned, otherwise the value passed as a default is returned.
|
||||
template <class Collection>
|
||||
const typename Collection::value_type::second_type&
|
||||
FindWithDefault(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& value) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return value;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Perform a lookup in a map or hash_map.
|
||||
// If the key is present a const pointer to the associated value is returned,
|
||||
// otherwise a NULL pointer is returned.
|
||||
template <class Collection>
|
||||
const typename Collection::value_type::second_type*
|
||||
FindOrNull(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return 0;
|
||||
}
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
// Perform a lookup in a map or hash_map, assuming that the key exists.
|
||||
// Crash if it does not.
|
||||
//
|
||||
// This is intended as a replacement for operator[] as an rvalue (for reading)
|
||||
// when the key is guaranteed to exist.
|
||||
//
|
||||
// operator[] is discouraged for several reasons:
|
||||
// * It has a side-effect of inserting missing keys
|
||||
// * It is not thread-safe (even when it is not inserting, it can still
|
||||
// choose to resize the underlying storage)
|
||||
// * It invalidates iterators (when it chooses to resize)
|
||||
// * It default constructs a value object even if it doesn't need to
|
||||
//
|
||||
// This version assumes the key is printable, and includes it in the fatal log
|
||||
// message.
|
||||
template <class Collection>
|
||||
const typename Collection::value_type::second_type&
|
||||
FindOrDie(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Perform a lookup in a map or hash_map whose values are pointers.
|
||||
// If the key is present a const pointer to the associated value is returned,
|
||||
// otherwise a NULL pointer is returned.
|
||||
// This function does not distinguish between a missing key and a key mapped
|
||||
// to a NULL value.
|
||||
template <class Collection>
|
||||
const typename Collection::value_type::second_type
|
||||
FindPtrOrNull(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return 0;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Change the value associated with a particular key in a map or hash_map.
|
||||
// If the key is not present in the map the key and value are inserted,
|
||||
// otherwise the value is updated to be a copy of the value provided.
|
||||
// True indicates that an insert took place, false indicates an update.
|
||||
template <class Collection, class Key, class Value>
|
||||
bool InsertOrUpdate(Collection * const collection,
|
||||
const Key& key, const Value& value) {
|
||||
pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(key, value));
|
||||
if (!ret.second) {
|
||||
// update
|
||||
ret.first->second = value;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Insert a new key and value into a map or hash_map.
|
||||
// If the key is not present in the map the key and value are
|
||||
// inserted, otherwise nothing happens. True indicates that an insert
|
||||
// took place, false indicates the key was already present.
|
||||
template <class Collection, class Key, class Value>
|
||||
bool InsertIfNotPresent(Collection * const collection,
|
||||
const Key& key, const Value& value) {
|
||||
pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(key, value));
|
||||
return ret.second;
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,361 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/io/coded_stream_inl.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
#ifndef _MSC_VER // MSVC doesn't like definitions of inline constants, GCC
|
||||
// requires them.
|
||||
const int WireFormatLite::kMessageSetItemStartTag;
|
||||
const int WireFormatLite::kMessageSetItemEndTag;
|
||||
const int WireFormatLite::kMessageSetTypeIdTag;
|
||||
const int WireFormatLite::kMessageSetMessageTag;
|
||||
|
||||
#endif
|
||||
|
||||
const int WireFormatLite::kMessageSetItemTagsSize =
|
||||
io::CodedOutputStream::StaticVarintSize32<kMessageSetItemStartTag>::value +
|
||||
io::CodedOutputStream::StaticVarintSize32<kMessageSetItemEndTag>::value +
|
||||
io::CodedOutputStream::StaticVarintSize32<kMessageSetTypeIdTag>::value +
|
||||
io::CodedOutputStream::StaticVarintSize32<kMessageSetMessageTag>::value;
|
||||
|
||||
const WireFormatLite::CppType
|
||||
WireFormatLite::kFieldTypeToCppTypeMap[MAX_FIELD_TYPE + 1] = {
|
||||
static_cast<CppType>(0), // 0 is reserved for errors
|
||||
|
||||
CPPTYPE_DOUBLE, // TYPE_DOUBLE
|
||||
CPPTYPE_FLOAT, // TYPE_FLOAT
|
||||
CPPTYPE_INT64, // TYPE_INT64
|
||||
CPPTYPE_UINT64, // TYPE_UINT64
|
||||
CPPTYPE_INT32, // TYPE_INT32
|
||||
CPPTYPE_UINT64, // TYPE_FIXED64
|
||||
CPPTYPE_UINT32, // TYPE_FIXED32
|
||||
CPPTYPE_BOOL, // TYPE_BOOL
|
||||
CPPTYPE_STRING, // TYPE_STRING
|
||||
CPPTYPE_MESSAGE, // TYPE_GROUP
|
||||
CPPTYPE_MESSAGE, // TYPE_MESSAGE
|
||||
CPPTYPE_STRING, // TYPE_BYTES
|
||||
CPPTYPE_UINT32, // TYPE_UINT32
|
||||
CPPTYPE_ENUM, // TYPE_ENUM
|
||||
CPPTYPE_INT32, // TYPE_SFIXED32
|
||||
CPPTYPE_INT64, // TYPE_SFIXED64
|
||||
CPPTYPE_INT32, // TYPE_SINT32
|
||||
CPPTYPE_INT64, // TYPE_SINT64
|
||||
};
|
||||
|
||||
const WireFormatLite::WireType
|
||||
WireFormatLite::kWireTypeForFieldType[MAX_FIELD_TYPE + 1] = {
|
||||
static_cast<WireFormatLite::WireType>(-1), // invalid
|
||||
WireFormatLite::WIRETYPE_FIXED64, // TYPE_DOUBLE
|
||||
WireFormatLite::WIRETYPE_FIXED32, // TYPE_FLOAT
|
||||
WireFormatLite::WIRETYPE_VARINT, // TYPE_INT64
|
||||
WireFormatLite::WIRETYPE_VARINT, // TYPE_UINT64
|
||||
WireFormatLite::WIRETYPE_VARINT, // TYPE_INT32
|
||||
WireFormatLite::WIRETYPE_FIXED64, // TYPE_FIXED64
|
||||
WireFormatLite::WIRETYPE_FIXED32, // TYPE_FIXED32
|
||||
WireFormatLite::WIRETYPE_VARINT, // TYPE_BOOL
|
||||
WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_STRING
|
||||
WireFormatLite::WIRETYPE_START_GROUP, // TYPE_GROUP
|
||||
WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_MESSAGE
|
||||
WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_BYTES
|
||||
WireFormatLite::WIRETYPE_VARINT, // TYPE_UINT32
|
||||
WireFormatLite::WIRETYPE_VARINT, // TYPE_ENUM
|
||||
WireFormatLite::WIRETYPE_FIXED32, // TYPE_SFIXED32
|
||||
WireFormatLite::WIRETYPE_FIXED64, // TYPE_SFIXED64
|
||||
WireFormatLite::WIRETYPE_VARINT, // TYPE_SINT32
|
||||
WireFormatLite::WIRETYPE_VARINT, // TYPE_SINT64
|
||||
};
|
||||
|
||||
bool WireFormatLite::SkipField(
|
||||
io::CodedInputStream* input, uint32 tag) {
|
||||
switch (WireFormatLite::GetTagWireType(tag)) {
|
||||
case WireFormatLite::WIRETYPE_VARINT: {
|
||||
uint64 value;
|
||||
if (!input->ReadVarint64(&value)) return false;
|
||||
return true;
|
||||
}
|
||||
case WireFormatLite::WIRETYPE_FIXED64: {
|
||||
uint64 value;
|
||||
if (!input->ReadLittleEndian64(&value)) return false;
|
||||
return true;
|
||||
}
|
||||
case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
|
||||
uint32 length;
|
||||
if (!input->ReadVarint32(&length)) return false;
|
||||
if (!input->Skip(length)) return false;
|
||||
return true;
|
||||
}
|
||||
case WireFormatLite::WIRETYPE_START_GROUP: {
|
||||
if (!input->IncrementRecursionDepth()) return false;
|
||||
if (!SkipMessage(input)) return false;
|
||||
input->DecrementRecursionDepth();
|
||||
// Check that the ending tag matched the starting tag.
|
||||
if (!input->LastTagWas(WireFormatLite::MakeTag(
|
||||
WireFormatLite::GetTagFieldNumber(tag),
|
||||
WireFormatLite::WIRETYPE_END_GROUP))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case WireFormatLite::WIRETYPE_END_GROUP: {
|
||||
return false;
|
||||
}
|
||||
case WireFormatLite::WIRETYPE_FIXED32: {
|
||||
uint32 value;
|
||||
if (!input->ReadLittleEndian32(&value)) return false;
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool WireFormatLite::SkipMessage(io::CodedInputStream* input) {
|
||||
while(true) {
|
||||
uint32 tag = input->ReadTag();
|
||||
if (tag == 0) {
|
||||
// End of input. This is a valid place to end, so return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
|
||||
|
||||
if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
|
||||
// Must be the end of the message.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!SkipField(input, tag)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool FieldSkipper::SkipField(
|
||||
io::CodedInputStream* input, uint32 tag) {
|
||||
return WireFormatLite::SkipField(input, tag);
|
||||
}
|
||||
|
||||
bool FieldSkipper::SkipMessage(io::CodedInputStream* input) {
|
||||
return WireFormatLite::SkipMessage(input);
|
||||
}
|
||||
|
||||
void FieldSkipper::SkipUnknownEnum(
|
||||
int field_number, int value) {
|
||||
// Nothing.
|
||||
}
|
||||
|
||||
bool WireFormatLite::ReadPackedEnumNoInline(io::CodedInputStream* input,
|
||||
bool (*is_valid)(int),
|
||||
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(value)) {
|
||||
values->Add(value);
|
||||
}
|
||||
}
|
||||
input->PopLimit(limit);
|
||||
return true;
|
||||
}
|
||||
|
||||
void WireFormatLite::WriteInt32(int field_number, int32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_VARINT, output);
|
||||
WriteInt32NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteInt64(int field_number, int64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_VARINT, output);
|
||||
WriteInt64NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteUInt32(int field_number, uint32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_VARINT, output);
|
||||
WriteUInt32NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteUInt64(int field_number, uint64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_VARINT, output);
|
||||
WriteUInt64NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteSInt32(int field_number, int32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_VARINT, output);
|
||||
WriteSInt32NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteSInt64(int field_number, int64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_VARINT, output);
|
||||
WriteSInt64NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteFixed32(int field_number, uint32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_FIXED32, output);
|
||||
WriteFixed32NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteFixed64(int field_number, uint64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_FIXED64, output);
|
||||
WriteFixed64NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteSFixed32(int field_number, int32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_FIXED32, output);
|
||||
WriteSFixed32NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteSFixed64(int field_number, int64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_FIXED64, output);
|
||||
WriteSFixed64NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteFloat(int field_number, float value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_FIXED32, output);
|
||||
WriteFloatNoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteDouble(int field_number, double value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_FIXED64, output);
|
||||
WriteDoubleNoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteBool(int field_number, bool value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_VARINT, output);
|
||||
WriteBoolNoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteEnum(int field_number, int value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_VARINT, output);
|
||||
WriteEnumNoTag(value, output);
|
||||
}
|
||||
|
||||
void WireFormatLite::WriteString(int field_number, const string& value,
|
||||
io::CodedOutputStream* output) {
|
||||
// String is for UTF-8 text only
|
||||
WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
|
||||
GOOGLE_CHECK(value.size() <= kint32max);
|
||||
output->WriteVarint32(value.size());
|
||||
output->WriteString(value);
|
||||
}
|
||||
void WireFormatLite::WriteBytes(int field_number, const string& value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
|
||||
GOOGLE_CHECK(value.size() <= kint32max);
|
||||
output->WriteVarint32(value.size());
|
||||
output->WriteString(value);
|
||||
}
|
||||
|
||||
|
||||
void WireFormatLite::WriteGroup(int field_number,
|
||||
const MessageLite& value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_START_GROUP, output);
|
||||
value.SerializeWithCachedSizes(output);
|
||||
WriteTag(field_number, WIRETYPE_END_GROUP, output);
|
||||
}
|
||||
|
||||
void WireFormatLite::WriteMessage(int field_number,
|
||||
const MessageLite& value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
|
||||
const int size = value.GetCachedSize();
|
||||
output->WriteVarint32(size);
|
||||
value.SerializeWithCachedSizes(output);
|
||||
}
|
||||
|
||||
void WireFormatLite::WriteGroupMaybeToArray(int field_number,
|
||||
const MessageLite& value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_START_GROUP, output);
|
||||
const int size = value.GetCachedSize();
|
||||
uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
|
||||
if (target != NULL) {
|
||||
uint8* end = value.SerializeWithCachedSizesToArray(target);
|
||||
GOOGLE_DCHECK_EQ(end - target, size);
|
||||
} else {
|
||||
value.SerializeWithCachedSizes(output);
|
||||
}
|
||||
WriteTag(field_number, WIRETYPE_END_GROUP, output);
|
||||
}
|
||||
|
||||
void WireFormatLite::WriteMessageMaybeToArray(int field_number,
|
||||
const MessageLite& value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
|
||||
const int size = value.GetCachedSize();
|
||||
output->WriteVarint32(size);
|
||||
uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
|
||||
if (target != NULL) {
|
||||
uint8* end = value.SerializeWithCachedSizesToArray(target);
|
||||
GOOGLE_DCHECK_EQ(end - target, size);
|
||||
} else {
|
||||
value.SerializeWithCachedSizes(output);
|
||||
}
|
||||
}
|
||||
|
||||
bool WireFormatLite::ReadString(io::CodedInputStream* input,
|
||||
string* value) {
|
||||
// String is for UTF-8 text only
|
||||
uint32 length;
|
||||
if (!input->ReadVarint32(&length)) return false;
|
||||
if (!input->InternalReadStringInline(value, length)) return false;
|
||||
return true;
|
||||
}
|
||||
bool WireFormatLite::ReadBytes(io::CodedInputStream* input,
|
||||
string* value) {
|
||||
uint32 length;
|
||||
if (!input->ReadVarint32(&length)) return false;
|
||||
return input->InternalReadStringInline(value, length);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -0,0 +1,895 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
if HAVE_ZLIB
|
||||
GZCHECKPROGRAMS = zcgzip zcgunzip
|
||||
GZHEADERS = google/protobuf/io/gzip_stream.h
|
||||
GZTESTS = google/protobuf/io/gzip_stream_unittest.sh
|
||||
ZLIB_DEF = -DHAVE_ZLIB=1
|
||||
else
|
||||
GZCHECKPROGRAMS =
|
||||
GZHEADERS =
|
||||
GZTESTS =
|
||||
ZLIB_DEF =
|
||||
endif
|
||||
|
||||
if HAVE_PTHREAD
|
||||
PTHREAD_DEF = -DHAVE_PTHREAD=1
|
||||
else
|
||||
PTHREAD_DEF =
|
||||
endif
|
||||
|
||||
if GCC
|
||||
# Turn on all warnings except for sign comparison (we ignore sign comparison
|
||||
# in Google so our code base have tons of such warnings).
|
||||
NO_OPT_CXXFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_DEF) $(ZLIB_DEF) -Wall -Wno-sign-compare
|
||||
else
|
||||
NO_OPT_CXXFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_DEF) $(ZLIB_DEF)
|
||||
endif
|
||||
|
||||
AM_CXXFLAGS = $(NO_OPT_CXXFLAGS) $(PROTOBUF_OPT_FLAG)
|
||||
|
||||
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)
|
||||
|
||||
# If you are adding new files here, also remember to change the build files for
|
||||
# all other languages, //protoc-artifacts/build-zip.sh and run
|
||||
# //update_file_list.sh for bazel.
|
||||
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 \
|
||||
testzip.jar testzip.list testzip.proto testzip.zip \
|
||||
no_warning_test.cc \
|
||||
google/protobuf/compiler/js/well_known_types_embed.cc \
|
||||
js_embed$(EXEEXT)
|
||||
|
||||
MAINTAINERCLEANFILES = \
|
||||
Makefile.in
|
||||
|
||||
nobase_include_HEADERS = \
|
||||
google/protobuf/stubs/atomic_sequence_num.h \
|
||||
google/protobuf/stubs/atomicops.h \
|
||||
google/protobuf/stubs/atomicops_internals_power.h \
|
||||
google/protobuf/stubs/atomicops_internals_ppc_gcc.h \
|
||||
google/protobuf/stubs/atomicops_internals_arm64_gcc.h \
|
||||
google/protobuf/stubs/atomicops_internals_arm_gcc.h \
|
||||
google/protobuf/stubs/atomicops_internals_arm_qnx.h \
|
||||
google/protobuf/stubs/atomicops_internals_atomicword_compat.h \
|
||||
google/protobuf/stubs/atomicops_internals_generic_c11_atomic.h \
|
||||
google/protobuf/stubs/atomicops_internals_generic_gcc.h \
|
||||
google/protobuf/stubs/atomicops_internals_macosx.h \
|
||||
google/protobuf/stubs/atomicops_internals_mips_gcc.h \
|
||||
google/protobuf/stubs/atomicops_internals_solaris.h \
|
||||
google/protobuf/stubs/atomicops_internals_tsan.h \
|
||||
google/protobuf/stubs/atomicops_internals_x86_gcc.h \
|
||||
google/protobuf/stubs/atomicops_internals_x86_msvc.h \
|
||||
google/protobuf/stubs/callback.h \
|
||||
google/protobuf/stubs/bytestream.h \
|
||||
google/protobuf/stubs/casts.h \
|
||||
google/protobuf/stubs/common.h \
|
||||
google/protobuf/stubs/fastmem.h \
|
||||
google/protobuf/stubs/hash.h \
|
||||
google/protobuf/stubs/logging.h \
|
||||
google/protobuf/stubs/macros.h \
|
||||
google/protobuf/stubs/mutex.h \
|
||||
google/protobuf/stubs/once.h \
|
||||
google/protobuf/stubs/platform_macros.h \
|
||||
google/protobuf/stubs/port.h \
|
||||
google/protobuf/stubs/scoped_ptr.h \
|
||||
google/protobuf/stubs/shared_ptr.h \
|
||||
google/protobuf/stubs/singleton.h \
|
||||
google/protobuf/stubs/status.h \
|
||||
google/protobuf/stubs/stl_util.h \
|
||||
google/protobuf/stubs/stringpiece.h \
|
||||
google/protobuf/stubs/template_util.h \
|
||||
google/protobuf/stubs/type_traits.h \
|
||||
google/protobuf/any.pb.h \
|
||||
google/protobuf/api.pb.h \
|
||||
google/protobuf/any.h \
|
||||
google/protobuf/arena.h \
|
||||
google/protobuf/arenastring.h \
|
||||
google/protobuf/descriptor_database.h \
|
||||
google/protobuf/descriptor.h \
|
||||
google/protobuf/descriptor.pb.h \
|
||||
google/protobuf/duration.pb.h \
|
||||
google/protobuf/dynamic_message.h \
|
||||
google/protobuf/empty.pb.h \
|
||||
google/protobuf/extension_set.h \
|
||||
google/protobuf/field_mask.pb.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/has_bits.h \
|
||||
google/protobuf/map_entry.h \
|
||||
google/protobuf/map_entry_lite.h \
|
||||
google/protobuf/map_field.h \
|
||||
google/protobuf/map_field_inl.h \
|
||||
google/protobuf/map_field_lite.h \
|
||||
google/protobuf/map.h \
|
||||
google/protobuf/map_type_handler.h \
|
||||
google/protobuf/message.h \
|
||||
google/protobuf/message_lite.h \
|
||||
google/protobuf/metadata.h \
|
||||
google/protobuf/reflection.h \
|
||||
google/protobuf/reflection_ops.h \
|
||||
google/protobuf/repeated_field.h \
|
||||
google/protobuf/service.h \
|
||||
google/protobuf/source_context.pb.h \
|
||||
google/protobuf/struct.pb.h \
|
||||
google/protobuf/text_format.h \
|
||||
google/protobuf/timestamp.pb.h \
|
||||
google/protobuf/type.pb.h \
|
||||
google/protobuf/unknown_field_set.h \
|
||||
google/protobuf/wire_format.h \
|
||||
google/protobuf/wire_format_lite.h \
|
||||
google/protobuf/wire_format_lite_inl.h \
|
||||
google/protobuf/wrappers.pb.h \
|
||||
google/protobuf/io/coded_stream.h \
|
||||
$(GZHEADERS) \
|
||||
google/protobuf/io/printer.h \
|
||||
google/protobuf/io/strtod.h \
|
||||
google/protobuf/io/tokenizer.h \
|
||||
google/protobuf/io/zero_copy_stream.h \
|
||||
google/protobuf/io/zero_copy_stream_impl.h \
|
||||
google/protobuf/io/zero_copy_stream_impl_lite.h \
|
||||
google/protobuf/compiler/code_generator.h \
|
||||
google/protobuf/compiler/command_line_interface.h \
|
||||
google/protobuf/compiler/importer.h \
|
||||
google/protobuf/compiler/parser.h \
|
||||
google/protobuf/compiler/plugin.h \
|
||||
google/protobuf/compiler/plugin.pb.h \
|
||||
google/protobuf/compiler/cpp/cpp_generator.h \
|
||||
google/protobuf/compiler/csharp/csharp_generator.h \
|
||||
google/protobuf/compiler/csharp/csharp_names.h \
|
||||
google/protobuf/compiler/java/java_generator.h \
|
||||
google/protobuf/compiler/java/java_names.h \
|
||||
google/protobuf/compiler/javanano/javanano_generator.h \
|
||||
google/protobuf/compiler/js/js_generator.h \
|
||||
google/protobuf/compiler/js/well_known_types_embed.h \
|
||||
google/protobuf/compiler/objectivec/objectivec_generator.h \
|
||||
google/protobuf/compiler/objectivec/objectivec_helpers.h \
|
||||
google/protobuf/compiler/php/php_generator.h \
|
||||
google/protobuf/compiler/python/python_generator.h \
|
||||
google/protobuf/compiler/ruby/ruby_generator.h \
|
||||
google/protobuf/util/type_resolver.h \
|
||||
google/protobuf/util/field_comparator.h \
|
||||
google/protobuf/util/field_mask_util.h \
|
||||
google/protobuf/util/json_util.h \
|
||||
google/protobuf/util/time_util.h \
|
||||
google/protobuf/util/type_resolver_util.h \
|
||||
google/protobuf/util/message_differencer.h
|
||||
|
||||
lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la
|
||||
|
||||
libprotobuf_lite_la_LIBADD = $(PTHREAD_LIBS)
|
||||
libprotobuf_lite_la_LDFLAGS = -version-info 12:0:0 -export-dynamic -no-undefined
|
||||
libprotobuf_lite_la_SOURCES = \
|
||||
google/protobuf/stubs/atomicops_internals_x86_gcc.cc \
|
||||
google/protobuf/stubs/atomicops_internals_x86_msvc.cc \
|
||||
google/protobuf/stubs/bytestream.cc \
|
||||
google/protobuf/stubs/bytestream.h \
|
||||
google/protobuf/stubs/common.cc \
|
||||
google/protobuf/stubs/hash.h \
|
||||
google/protobuf/stubs/int128.cc \
|
||||
google/protobuf/stubs/int128.h \
|
||||
google/protobuf/stubs/map_util.h \
|
||||
google/protobuf/stubs/mathutil.h \
|
||||
google/protobuf/stubs/once.cc \
|
||||
google/protobuf/stubs/shared_ptr.h \
|
||||
google/protobuf/stubs/status.cc \
|
||||
google/protobuf/stubs/status.h \
|
||||
google/protobuf/stubs/status_macros.h \
|
||||
google/protobuf/stubs/statusor.cc \
|
||||
google/protobuf/stubs/statusor.h \
|
||||
google/protobuf/stubs/stringpiece.cc \
|
||||
google/protobuf/stubs/stringpiece.h \
|
||||
google/protobuf/stubs/stringprintf.cc \
|
||||
google/protobuf/stubs/stringprintf.h \
|
||||
google/protobuf/stubs/structurally_valid.cc \
|
||||
google/protobuf/stubs/strutil.cc \
|
||||
google/protobuf/stubs/strutil.h \
|
||||
google/protobuf/stubs/time.cc \
|
||||
google/protobuf/stubs/time.h \
|
||||
google/protobuf/arena.cc \
|
||||
google/protobuf/arenastring.cc \
|
||||
google/protobuf/extension_set.cc \
|
||||
google/protobuf/generated_message_util.cc \
|
||||
google/protobuf/message_lite.cc \
|
||||
google/protobuf/repeated_field.cc \
|
||||
google/protobuf/wire_format_lite.cc \
|
||||
google/protobuf/io/coded_stream.cc \
|
||||
google/protobuf/io/coded_stream_inl.h \
|
||||
google/protobuf/io/zero_copy_stream.cc \
|
||||
google/protobuf/io/zero_copy_stream_impl_lite.cc
|
||||
|
||||
libprotobuf_la_LIBADD = $(PTHREAD_LIBS)
|
||||
libprotobuf_la_LDFLAGS = -version-info 12:0:0 -export-dynamic -no-undefined
|
||||
libprotobuf_la_SOURCES = \
|
||||
$(libprotobuf_lite_la_SOURCES) \
|
||||
google/protobuf/any.pb.cc \
|
||||
google/protobuf/api.pb.cc \
|
||||
google/protobuf/stubs/mathlimits.cc \
|
||||
google/protobuf/stubs/mathlimits.h \
|
||||
google/protobuf/any.cc \
|
||||
google/protobuf/descriptor.cc \
|
||||
google/protobuf/descriptor_database.cc \
|
||||
google/protobuf/descriptor.pb.cc \
|
||||
google/protobuf/duration.pb.cc \
|
||||
google/protobuf/dynamic_message.cc \
|
||||
google/protobuf/empty.pb.cc \
|
||||
google/protobuf/extension_set_heavy.cc \
|
||||
google/protobuf/field_mask.pb.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 \
|
||||
google/protobuf/service.cc \
|
||||
google/protobuf/source_context.pb.cc \
|
||||
google/protobuf/struct.pb.cc \
|
||||
google/protobuf/stubs/substitute.cc \
|
||||
google/protobuf/stubs/substitute.h \
|
||||
google/protobuf/text_format.cc \
|
||||
google/protobuf/timestamp.pb.cc \
|
||||
google/protobuf/type.pb.cc \
|
||||
google/protobuf/unknown_field_set.cc \
|
||||
google/protobuf/wire_format.cc \
|
||||
google/protobuf/wrappers.pb.cc \
|
||||
google/protobuf/io/gzip_stream.cc \
|
||||
google/protobuf/io/printer.cc \
|
||||
google/protobuf/io/strtod.cc \
|
||||
google/protobuf/io/tokenizer.cc \
|
||||
google/protobuf/io/zero_copy_stream_impl.cc \
|
||||
google/protobuf/compiler/importer.cc \
|
||||
google/protobuf/compiler/parser.cc \
|
||||
google/protobuf/util/field_comparator.cc \
|
||||
google/protobuf/util/field_mask_util.cc \
|
||||
google/protobuf/util/internal/constants.h \
|
||||
google/protobuf/util/internal/datapiece.cc \
|
||||
google/protobuf/util/internal/datapiece.h \
|
||||
google/protobuf/util/internal/default_value_objectwriter.cc \
|
||||
google/protobuf/util/internal/default_value_objectwriter.h \
|
||||
google/protobuf/util/internal/error_listener.cc \
|
||||
google/protobuf/util/internal/error_listener.h \
|
||||
google/protobuf/util/internal/expecting_objectwriter.h \
|
||||
google/protobuf/util/internal/field_mask_utility.cc \
|
||||
google/protobuf/util/internal/field_mask_utility.h \
|
||||
google/protobuf/util/internal/json_escaping.cc \
|
||||
google/protobuf/util/internal/json_escaping.h \
|
||||
google/protobuf/util/internal/json_objectwriter.cc \
|
||||
google/protobuf/util/internal/json_objectwriter.h \
|
||||
google/protobuf/util/internal/json_stream_parser.cc \
|
||||
google/protobuf/util/internal/json_stream_parser.h \
|
||||
google/protobuf/util/internal/location_tracker.h \
|
||||
google/protobuf/util/internal/mock_error_listener.h \
|
||||
google/protobuf/util/internal/object_location_tracker.h \
|
||||
google/protobuf/util/internal/object_source.h \
|
||||
google/protobuf/util/internal/object_writer.cc \
|
||||
google/protobuf/util/internal/object_writer.h \
|
||||
google/protobuf/util/internal/protostream_objectsource.cc \
|
||||
google/protobuf/util/internal/protostream_objectsource.h \
|
||||
google/protobuf/util/internal/protostream_objectwriter.cc \
|
||||
google/protobuf/util/internal/protostream_objectwriter.h \
|
||||
google/protobuf/util/internal/proto_writer.cc \
|
||||
google/protobuf/util/internal/proto_writer.h \
|
||||
google/protobuf/util/internal/structured_objectwriter.h \
|
||||
google/protobuf/util/internal/type_info.cc \
|
||||
google/protobuf/util/internal/type_info.h \
|
||||
google/protobuf/util/internal/type_info_test_helper.cc \
|
||||
google/protobuf/util/internal/type_info_test_helper.h \
|
||||
google/protobuf/util/internal/utility.cc \
|
||||
google/protobuf/util/internal/utility.h \
|
||||
google/protobuf/util/json_util.cc \
|
||||
google/protobuf/util/message_differencer.cc \
|
||||
google/protobuf/util/time_util.cc \
|
||||
google/protobuf/util/type_resolver_util.cc
|
||||
|
||||
nodist_libprotobuf_la_SOURCES = $(nodist_libprotobuf_lite_la_SOURCES)
|
||||
|
||||
libprotoc_la_LIBADD = $(PTHREAD_LIBS) libprotobuf.la
|
||||
libprotoc_la_LDFLAGS = -version-info 12:0:0 -export-dynamic -no-undefined
|
||||
libprotoc_la_SOURCES = \
|
||||
google/protobuf/compiler/code_generator.cc \
|
||||
google/protobuf/compiler/command_line_interface.cc \
|
||||
google/protobuf/compiler/plugin.cc \
|
||||
google/protobuf/compiler/plugin.pb.cc \
|
||||
google/protobuf/compiler/subprocess.cc \
|
||||
google/protobuf/compiler/subprocess.h \
|
||||
google/protobuf/compiler/zip_writer.cc \
|
||||
google/protobuf/compiler/zip_writer.h \
|
||||
google/protobuf/compiler/cpp/cpp_enum.cc \
|
||||
google/protobuf/compiler/cpp/cpp_enum.h \
|
||||
google/protobuf/compiler/cpp/cpp_enum_field.cc \
|
||||
google/protobuf/compiler/cpp/cpp_enum_field.h \
|
||||
google/protobuf/compiler/cpp/cpp_extension.cc \
|
||||
google/protobuf/compiler/cpp/cpp_extension.h \
|
||||
google/protobuf/compiler/cpp/cpp_field.cc \
|
||||
google/protobuf/compiler/cpp/cpp_field.h \
|
||||
google/protobuf/compiler/cpp/cpp_file.cc \
|
||||
google/protobuf/compiler/cpp/cpp_file.h \
|
||||
google/protobuf/compiler/cpp/cpp_generator.cc \
|
||||
google/protobuf/compiler/cpp/cpp_helpers.cc \
|
||||
google/protobuf/compiler/cpp/cpp_helpers.h \
|
||||
google/protobuf/compiler/cpp/cpp_map_field.cc \
|
||||
google/protobuf/compiler/cpp/cpp_map_field.h \
|
||||
google/protobuf/compiler/cpp/cpp_message.cc \
|
||||
google/protobuf/compiler/cpp/cpp_message.h \
|
||||
google/protobuf/compiler/cpp/cpp_message_field.cc \
|
||||
google/protobuf/compiler/cpp/cpp_message_field.h \
|
||||
google/protobuf/compiler/cpp/cpp_options.h \
|
||||
google/protobuf/compiler/cpp/cpp_primitive_field.cc \
|
||||
google/protobuf/compiler/cpp/cpp_primitive_field.h \
|
||||
google/protobuf/compiler/cpp/cpp_service.cc \
|
||||
google/protobuf/compiler/cpp/cpp_service.h \
|
||||
google/protobuf/compiler/cpp/cpp_string_field.cc \
|
||||
google/protobuf/compiler/cpp/cpp_string_field.h \
|
||||
google/protobuf/compiler/java/java_context.cc \
|
||||
google/protobuf/compiler/java/java_context.h \
|
||||
google/protobuf/compiler/java/java_enum.cc \
|
||||
google/protobuf/compiler/java/java_enum_lite.cc \
|
||||
google/protobuf/compiler/java/java_enum_field.cc \
|
||||
google/protobuf/compiler/java/java_enum_field.h \
|
||||
google/protobuf/compiler/java/java_enum_field_lite.cc \
|
||||
google/protobuf/compiler/java/java_enum_field_lite.h \
|
||||
google/protobuf/compiler/java/java_enum.h \
|
||||
google/protobuf/compiler/java/java_enum_lite.h \
|
||||
google/protobuf/compiler/java/java_extension.cc \
|
||||
google/protobuf/compiler/java/java_extension.h \
|
||||
google/protobuf/compiler/java/java_extension_lite.cc \
|
||||
google/protobuf/compiler/java/java_extension_lite.h \
|
||||
google/protobuf/compiler/java/java_field.cc \
|
||||
google/protobuf/compiler/java/java_field.h \
|
||||
google/protobuf/compiler/java/java_file.cc \
|
||||
google/protobuf/compiler/java/java_file.h \
|
||||
google/protobuf/compiler/java/java_generator.cc \
|
||||
google/protobuf/compiler/java/java_generator_factory.cc \
|
||||
google/protobuf/compiler/java/java_generator_factory.h \
|
||||
google/protobuf/compiler/java/java_helpers.cc \
|
||||
google/protobuf/compiler/java/java_helpers.h \
|
||||
google/protobuf/compiler/java/java_lazy_message_field.cc \
|
||||
google/protobuf/compiler/java/java_lazy_message_field.h \
|
||||
google/protobuf/compiler/java/java_lazy_message_field_lite.cc\
|
||||
google/protobuf/compiler/java/java_lazy_message_field_lite.h \
|
||||
google/protobuf/compiler/java/java_map_field.cc \
|
||||
google/protobuf/compiler/java/java_map_field.h \
|
||||
google/protobuf/compiler/java/java_map_field_lite.cc \
|
||||
google/protobuf/compiler/java/java_map_field_lite.h \
|
||||
google/protobuf/compiler/java/java_message.cc \
|
||||
google/protobuf/compiler/java/java_message_lite.cc \
|
||||
google/protobuf/compiler/java/java_message_builder.cc \
|
||||
google/protobuf/compiler/java/java_message_builder_lite.cc \
|
||||
google/protobuf/compiler/java/java_message_field.cc \
|
||||
google/protobuf/compiler/java/java_message_field.h \
|
||||
google/protobuf/compiler/java/java_message_field_lite.cc \
|
||||
google/protobuf/compiler/java/java_message_field_lite.h \
|
||||
google/protobuf/compiler/java/java_message.h \
|
||||
google/protobuf/compiler/java/java_message_lite.h \
|
||||
google/protobuf/compiler/java/java_message_builder.h \
|
||||
google/protobuf/compiler/java/java_message_builder_lite.h \
|
||||
google/protobuf/compiler/java/java_name_resolver.cc \
|
||||
google/protobuf/compiler/java/java_name_resolver.h \
|
||||
google/protobuf/compiler/java/java_options.h \
|
||||
google/protobuf/compiler/java/java_primitive_field.cc \
|
||||
google/protobuf/compiler/java/java_primitive_field.h \
|
||||
google/protobuf/compiler/java/java_primitive_field_lite.cc \
|
||||
google/protobuf/compiler/java/java_primitive_field_lite.h \
|
||||
google/protobuf/compiler/java/java_shared_code_generator.cc \
|
||||
google/protobuf/compiler/java/java_shared_code_generator.h \
|
||||
google/protobuf/compiler/java/java_service.cc \
|
||||
google/protobuf/compiler/java/java_service.h \
|
||||
google/protobuf/compiler/java/java_string_field.cc \
|
||||
google/protobuf/compiler/java/java_string_field.h \
|
||||
google/protobuf/compiler/java/java_string_field_lite.cc \
|
||||
google/protobuf/compiler/java/java_string_field_lite.h \
|
||||
google/protobuf/compiler/java/java_doc_comment.cc \
|
||||
google/protobuf/compiler/java/java_doc_comment.h \
|
||||
google/protobuf/compiler/js/js_generator.cc \
|
||||
google/protobuf/compiler/js/well_known_types_embed.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/php/php_generator.cc \
|
||||
google/protobuf/compiler/python/python_generator.cc \
|
||||
google/protobuf/compiler/ruby/ruby_generator.cc \
|
||||
google/protobuf/compiler/csharp/csharp_doc_comment.cc \
|
||||
google/protobuf/compiler/csharp/csharp_doc_comment.h \
|
||||
google/protobuf/compiler/csharp/csharp_enum.cc \
|
||||
google/protobuf/compiler/csharp/csharp_enum.h \
|
||||
google/protobuf/compiler/csharp/csharp_enum_field.cc \
|
||||
google/protobuf/compiler/csharp/csharp_enum_field.h \
|
||||
google/protobuf/compiler/csharp/csharp_field_base.cc \
|
||||
google/protobuf/compiler/csharp/csharp_field_base.h \
|
||||
google/protobuf/compiler/csharp/csharp_generator.cc \
|
||||
google/protobuf/compiler/csharp/csharp_helpers.cc \
|
||||
google/protobuf/compiler/csharp/csharp_helpers.h \
|
||||
google/protobuf/compiler/csharp/csharp_map_field.cc \
|
||||
google/protobuf/compiler/csharp/csharp_map_field.h \
|
||||
google/protobuf/compiler/csharp/csharp_message.cc \
|
||||
google/protobuf/compiler/csharp/csharp_message.h \
|
||||
google/protobuf/compiler/csharp/csharp_message_field.cc \
|
||||
google/protobuf/compiler/csharp/csharp_message_field.h \
|
||||
google/protobuf/compiler/csharp/csharp_options.h \
|
||||
google/protobuf/compiler/csharp/csharp_primitive_field.cc \
|
||||
google/protobuf/compiler/csharp/csharp_primitive_field.h \
|
||||
google/protobuf/compiler/csharp/csharp_reflection_class.cc \
|
||||
google/protobuf/compiler/csharp/csharp_reflection_class.h \
|
||||
google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc \
|
||||
google/protobuf/compiler/csharp/csharp_repeated_enum_field.h \
|
||||
google/protobuf/compiler/csharp/csharp_repeated_message_field.cc \
|
||||
google/protobuf/compiler/csharp/csharp_repeated_message_field.h \
|
||||
google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc \
|
||||
google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h \
|
||||
google/protobuf/compiler/csharp/csharp_source_generator_base.cc \
|
||||
google/protobuf/compiler/csharp/csharp_source_generator_base.h \
|
||||
google/protobuf/compiler/csharp/csharp_wrapper_field.cc \
|
||||
google/protobuf/compiler/csharp/csharp_wrapper_field.h
|
||||
|
||||
bin_PROGRAMS = protoc
|
||||
protoc_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la
|
||||
protoc_SOURCES = google/protobuf/compiler/main.cc
|
||||
|
||||
# The special JS code for the well-known types is linked into the compiler via
|
||||
# well_known_types_embed.cc, which is generated from .js source files. We have
|
||||
# to build the js_embed binary using $(CXX_FOR_BUILD) so that it is executable
|
||||
# on the build machine in a cross-compilation setup.
|
||||
js_embed$(EXEEXT): $(srcdir)/google/protobuf/compiler/js/embed.cc
|
||||
$(CXX_FOR_BUILD) -o $@ $<
|
||||
js_well_known_types_sources = \
|
||||
google/protobuf/compiler/js/well_known_types/any.js \
|
||||
google/protobuf/compiler/js/well_known_types/struct.js \
|
||||
google/protobuf/compiler/js/well_known_types/timestamp.js
|
||||
# We have to cd to $(srcdir) so that out-of-tree builds work properly.
|
||||
google/protobuf/compiler/js/well_known_types_embed.cc: js_embed$(EXEEXT) $(js_well_known_types_sources)
|
||||
oldpwd=`pwd` && cd $(srcdir) && \
|
||||
$$oldpwd/js_embed$(EXEEXT) $(js_well_known_types_sources) > $$oldpwd/$@
|
||||
|
||||
# Tests ==============================================================
|
||||
|
||||
protoc_inputs = \
|
||||
google/protobuf/any_test.proto \
|
||||
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto \
|
||||
google/protobuf/map_lite_unittest.proto \
|
||||
google/protobuf/map_proto2_unittest.proto \
|
||||
google/protobuf/map_unittest.proto \
|
||||
google/protobuf/unittest_arena.proto \
|
||||
google/protobuf/unittest_custom_options.proto \
|
||||
google/protobuf/unittest_drop_unknown_fields.proto \
|
||||
google/protobuf/unittest_embed_optimize_for.proto \
|
||||
google/protobuf/unittest_empty.proto \
|
||||
google/protobuf/unittest_enormous_descriptor.proto \
|
||||
google/protobuf/unittest_import_lite.proto \
|
||||
google/protobuf/unittest_import.proto \
|
||||
google/protobuf/unittest_import_public_lite.proto \
|
||||
google/protobuf/unittest_import_public.proto \
|
||||
google/protobuf/unittest_lite_imports_nonlite.proto \
|
||||
google/protobuf/unittest_lite.proto \
|
||||
google/protobuf/unittest_mset.proto \
|
||||
google/protobuf/unittest_mset_wire_format.proto \
|
||||
google/protobuf/unittest_no_arena_lite.proto \
|
||||
google/protobuf/unittest_no_arena_import.proto \
|
||||
google/protobuf/unittest_no_arena.proto \
|
||||
google/protobuf/unittest_no_field_presence.proto \
|
||||
google/protobuf/unittest_no_generic_services.proto \
|
||||
google/protobuf/unittest_optimize_for.proto \
|
||||
google/protobuf/unittest_preserve_unknown_enum2.proto \
|
||||
google/protobuf/unittest_preserve_unknown_enum.proto \
|
||||
google/protobuf/unittest.proto \
|
||||
google/protobuf/unittest_proto3_arena.proto \
|
||||
google/protobuf/unittest_proto3_arena_lite.proto \
|
||||
google/protobuf/unittest_proto3_lite.proto \
|
||||
google/protobuf/unittest_well_known_types.proto \
|
||||
google/protobuf/util/internal/testdata/anys.proto \
|
||||
google/protobuf/util/internal/testdata/books.proto \
|
||||
google/protobuf/util/internal/testdata/default_value.proto \
|
||||
google/protobuf/util/internal/testdata/default_value_test.proto \
|
||||
google/protobuf/util/internal/testdata/field_mask.proto \
|
||||
google/protobuf/util/internal/testdata/maps.proto \
|
||||
google/protobuf/util/internal/testdata/oneofs.proto \
|
||||
google/protobuf/util/internal/testdata/proto3.proto \
|
||||
google/protobuf/util/internal/testdata/struct.proto \
|
||||
google/protobuf/util/internal/testdata/timestamp_duration.proto \
|
||||
google/protobuf/util/internal/testdata/wrappers.proto \
|
||||
google/protobuf/util/json_format_proto3.proto \
|
||||
google/protobuf/util/message_differencer_unittest.proto \
|
||||
google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(protoc_inputs) \
|
||||
$(js_well_known_types_sources) \
|
||||
solaris/libstdc++.la \
|
||||
google/protobuf/io/gzip_stream.h \
|
||||
google/protobuf/io/gzip_stream_unittest.sh \
|
||||
google/protobuf/testdata/golden_message \
|
||||
google/protobuf/testdata/golden_message_maps \
|
||||
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/map_test_data.txt \
|
||||
google/protobuf/testdata/text_format_unittest_data.txt \
|
||||
google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt \
|
||||
google/protobuf/testdata/text_format_unittest_data_pointy.txt \
|
||||
google/protobuf/testdata/text_format_unittest_data_pointy_oneof.txt \
|
||||
google/protobuf/testdata/text_format_unittest_extensions_data.txt \
|
||||
google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt \
|
||||
google/protobuf/package_info.h \
|
||||
google/protobuf/io/package_info.h \
|
||||
google/protobuf/util/package_info.h \
|
||||
google/protobuf/compiler/js/embed.cc \
|
||||
google/protobuf/compiler/ruby/ruby_generated_code.proto \
|
||||
google/protobuf/compiler/ruby/ruby_generated_code_pb.rb \
|
||||
google/protobuf/compiler/package_info.h \
|
||||
google/protobuf/compiler/zip_output_unittest.sh \
|
||||
README.md
|
||||
|
||||
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_no_arena_lite.pb.cc \
|
||||
google/protobuf/unittest_no_arena_lite.pb.h \
|
||||
google/protobuf/unittest_import_lite.pb.cc \
|
||||
google/protobuf/unittest_import_lite.pb.h \
|
||||
google/protobuf/unittest_import_public_lite.pb.cc \
|
||||
google/protobuf/unittest_import_public_lite.pb.h
|
||||
|
||||
protoc_outputs = \
|
||||
$(protoc_lite_outputs) \
|
||||
google/protobuf/any_test.pb.cc \
|
||||
google/protobuf/any_test.pb.h \
|
||||
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc \
|
||||
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h \
|
||||
google/protobuf/compiler/cpp/cpp_test_large_enum_value.pb.cc \
|
||||
google/protobuf/compiler/cpp/cpp_test_large_enum_value.pb.h \
|
||||
google/protobuf/map_proto2_unittest.pb.cc \
|
||||
google/protobuf/map_proto2_unittest.pb.h \
|
||||
google/protobuf/map_unittest.pb.cc \
|
||||
google/protobuf/map_unittest.pb.h \
|
||||
google/protobuf/unittest_arena.pb.cc \
|
||||
google/protobuf/unittest_arena.pb.h \
|
||||
google/protobuf/unittest_custom_options.pb.cc \
|
||||
google/protobuf/unittest_custom_options.pb.h \
|
||||
google/protobuf/unittest_drop_unknown_fields.pb.cc \
|
||||
google/protobuf/unittest_drop_unknown_fields.pb.h \
|
||||
google/protobuf/unittest_embed_optimize_for.pb.cc \
|
||||
google/protobuf/unittest_embed_optimize_for.pb.h \
|
||||
google/protobuf/unittest_empty.pb.cc \
|
||||
google/protobuf/unittest_empty.pb.h \
|
||||
google/protobuf/unittest_enormous_descriptor.pb.cc \
|
||||
google/protobuf/unittest_enormous_descriptor.pb.h \
|
||||
google/protobuf/unittest_import.pb.cc \
|
||||
google/protobuf/unittest_import.pb.h \
|
||||
google/protobuf/unittest_import_public.pb.cc \
|
||||
google/protobuf/unittest_import_public.pb.h \
|
||||
google/protobuf/unittest_lite_imports_nonlite.pb.cc \
|
||||
google/protobuf/unittest_lite_imports_nonlite.pb.h \
|
||||
google/protobuf/unittest_mset.pb.cc \
|
||||
google/protobuf/unittest_mset.pb.h \
|
||||
google/protobuf/unittest_mset_wire_format.pb.cc \
|
||||
google/protobuf/unittest_mset_wire_format.pb.h \
|
||||
google/protobuf/unittest_no_arena_import.pb.cc \
|
||||
google/protobuf/unittest_no_arena_import.pb.h \
|
||||
google/protobuf/unittest_no_arena.pb.cc \
|
||||
google/protobuf/unittest_no_arena.pb.h \
|
||||
google/protobuf/unittest_no_field_presence.pb.cc \
|
||||
google/protobuf/unittest_no_field_presence.pb.h \
|
||||
google/protobuf/unittest_no_generic_services.pb.cc \
|
||||
google/protobuf/unittest_no_generic_services.pb.h \
|
||||
google/protobuf/unittest_optimize_for.pb.cc \
|
||||
google/protobuf/unittest_optimize_for.pb.h \
|
||||
google/protobuf/unittest.pb.cc \
|
||||
google/protobuf/unittest.pb.h \
|
||||
google/protobuf/unittest_preserve_unknown_enum2.pb.cc \
|
||||
google/protobuf/unittest_preserve_unknown_enum2.pb.h \
|
||||
google/protobuf/unittest_preserve_unknown_enum.pb.cc \
|
||||
google/protobuf/unittest_preserve_unknown_enum.pb.h \
|
||||
google/protobuf/unittest_proto3_arena.pb.cc \
|
||||
google/protobuf/unittest_proto3_arena.pb.h \
|
||||
google/protobuf/unittest_proto3_arena_lite.pb.cc \
|
||||
google/protobuf/unittest_proto3_arena_lite.pb.h \
|
||||
google/protobuf/unittest_proto3_lite.pb.cc \
|
||||
google/protobuf/unittest_proto3_lite.pb.h \
|
||||
google/protobuf/unittest_well_known_types.pb.cc \
|
||||
google/protobuf/unittest_well_known_types.pb.h \
|
||||
google/protobuf/util/internal/testdata/anys.pb.cc \
|
||||
google/protobuf/util/internal/testdata/anys.pb.h \
|
||||
google/protobuf/util/internal/testdata/books.pb.cc \
|
||||
google/protobuf/util/internal/testdata/books.pb.h \
|
||||
google/protobuf/util/internal/testdata/default_value.pb.cc \
|
||||
google/protobuf/util/internal/testdata/default_value.pb.h \
|
||||
google/protobuf/util/internal/testdata/default_value_test.pb.cc \
|
||||
google/protobuf/util/internal/testdata/default_value_test.pb.h \
|
||||
google/protobuf/util/internal/testdata/field_mask.pb.cc \
|
||||
google/protobuf/util/internal/testdata/field_mask.pb.h \
|
||||
google/protobuf/util/internal/testdata/maps.pb.cc \
|
||||
google/protobuf/util/internal/testdata/maps.pb.h \
|
||||
google/protobuf/util/internal/testdata/oneofs.pb.cc \
|
||||
google/protobuf/util/internal/testdata/oneofs.pb.h \
|
||||
google/protobuf/util/internal/testdata/proto3.pb.cc \
|
||||
google/protobuf/util/internal/testdata/proto3.pb.h \
|
||||
google/protobuf/util/internal/testdata/struct.pb.cc \
|
||||
google/protobuf/util/internal/testdata/struct.pb.h \
|
||||
google/protobuf/util/internal/testdata/timestamp_duration.pb.cc \
|
||||
google/protobuf/util/internal/testdata/timestamp_duration.pb.h \
|
||||
google/protobuf/util/internal/testdata/wrappers.pb.cc \
|
||||
google/protobuf/util/internal/testdata/wrappers.pb.h \
|
||||
google/protobuf/util/json_format_proto3.pb.cc \
|
||||
google/protobuf/util/json_format_proto3.pb.h \
|
||||
google/protobuf/util/message_differencer_unittest.pb.cc \
|
||||
google/protobuf/util/message_differencer_unittest.pb.h
|
||||
|
||||
BUILT_SOURCES = $(protoc_outputs) google/protobuf/compiler/js/well_known_types_embed.cc
|
||||
|
||||
if USE_EXTERNAL_PROTOC
|
||||
|
||||
unittest_proto_middleman: $(protoc_inputs)
|
||||
$(PROTOC) -I$(srcdir) --cpp_out=. $^
|
||||
touch unittest_proto_middleman
|
||||
|
||||
else
|
||||
|
||||
# We have to cd to $(srcdir) before executing protoc because $(protoc_inputs) is
|
||||
# relative to srcdir, which may not be the same as the current directory when
|
||||
# building out-of-tree.
|
||||
unittest_proto_middleman: protoc$(EXEEXT) $(protoc_inputs)
|
||||
oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/protoc$(EXEEXT) -I. --cpp_out=$$oldpwd $(protoc_inputs) )
|
||||
touch unittest_proto_middleman
|
||||
|
||||
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 \
|
||||
google/protobuf/testing/googletest.h \
|
||||
google/protobuf/testing/file.cc \
|
||||
google/protobuf/testing/file.h
|
||||
|
||||
check_PROGRAMS = protoc protobuf-test protobuf-lazy-descriptor-test \
|
||||
protobuf-lite-test test_plugin protobuf-lite-arena-test \
|
||||
no-warning-test $(GZCHECKPROGRAMS)
|
||||
protobuf_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \
|
||||
../gmock/gtest/lib/libgtest.la \
|
||||
../gmock/lib/libgmock.la \
|
||||
../gmock/lib/libgmock_main.la
|
||||
protobuf_test_CPPFLAGS = -I$(srcdir)/../gmock/gtest/include \
|
||||
-I$(srcdir)/../gmock/include
|
||||
# Disable optimization for tests unless the user explicitly asked for it,
|
||||
# since test_util.cc takes forever to compile with optimization (with GCC).
|
||||
# See configure.ac for more info.
|
||||
protobuf_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
|
||||
protobuf_test_SOURCES = \
|
||||
google/protobuf/stubs/bytestream_unittest.cc \
|
||||
google/protobuf/stubs/common_unittest.cc \
|
||||
google/protobuf/stubs/int128_unittest.cc \
|
||||
google/protobuf/stubs/once_unittest.cc \
|
||||
google/protobuf/stubs/statusor_test.cc \
|
||||
google/protobuf/stubs/status_test.cc \
|
||||
google/protobuf/stubs/stringpiece_unittest.cc \
|
||||
google/protobuf/stubs/stringprintf_unittest.cc \
|
||||
google/protobuf/stubs/structurally_valid_unittest.cc \
|
||||
google/protobuf/stubs/strutil_unittest.cc \
|
||||
google/protobuf/stubs/template_util_unittest.cc \
|
||||
google/protobuf/stubs/time_test.cc \
|
||||
google/protobuf/stubs/type_traits_unittest.cc \
|
||||
google/protobuf/any_test.cc \
|
||||
google/protobuf/arenastring_unittest.cc \
|
||||
google/protobuf/arena_unittest.cc \
|
||||
google/protobuf/descriptor_database_unittest.cc \
|
||||
google/protobuf/descriptor_unittest.cc \
|
||||
google/protobuf/drop_unknown_fields_test.cc \
|
||||
google/protobuf/dynamic_message_unittest.cc \
|
||||
google/protobuf/extension_set_unittest.cc \
|
||||
google/protobuf/generated_message_reflection_unittest.cc \
|
||||
google/protobuf/map_field_test.cc \
|
||||
google/protobuf/map_test.cc \
|
||||
google/protobuf/message_unittest.cc \
|
||||
google/protobuf/no_field_presence_test.cc \
|
||||
google/protobuf/preserve_unknown_enum_test.cc \
|
||||
google/protobuf/proto3_arena_unittest.cc \
|
||||
google/protobuf/proto3_arena_lite_unittest.cc \
|
||||
google/protobuf/proto3_lite_unittest.cc \
|
||||
google/protobuf/reflection_ops_unittest.cc \
|
||||
google/protobuf/repeated_field_reflection_unittest.cc \
|
||||
google/protobuf/repeated_field_unittest.cc \
|
||||
google/protobuf/text_format_unittest.cc \
|
||||
google/protobuf/unknown_field_set_unittest.cc \
|
||||
google/protobuf/well_known_types_unittest.cc \
|
||||
google/protobuf/wire_format_unittest.cc \
|
||||
google/protobuf/io/coded_stream_unittest.cc \
|
||||
google/protobuf/io/printer_unittest.cc \
|
||||
google/protobuf/io/tokenizer_unittest.cc \
|
||||
google/protobuf/io/zero_copy_stream_unittest.cc \
|
||||
google/protobuf/compiler/command_line_interface_unittest.cc \
|
||||
google/protobuf/compiler/importer_unittest.cc \
|
||||
google/protobuf/compiler/mock_code_generator.cc \
|
||||
google/protobuf/compiler/mock_code_generator.h \
|
||||
google/protobuf/compiler/parser_unittest.cc \
|
||||
google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc \
|
||||
google/protobuf/compiler/cpp/cpp_unittest.h \
|
||||
google/protobuf/compiler/cpp/cpp_unittest.cc \
|
||||
google/protobuf/compiler/cpp/cpp_plugin_unittest.cc \
|
||||
google/protobuf/compiler/cpp/metadata_test.cc \
|
||||
google/protobuf/compiler/java/java_plugin_unittest.cc \
|
||||
google/protobuf/compiler/java/java_doc_comment_unittest.cc \
|
||||
google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc \
|
||||
google/protobuf/compiler/python/python_plugin_unittest.cc \
|
||||
google/protobuf/compiler/ruby/ruby_generator_unittest.cc \
|
||||
google/protobuf/compiler/csharp/csharp_generator_unittest.cc \
|
||||
google/protobuf/util/field_comparator_test.cc \
|
||||
google/protobuf/util/field_mask_util_test.cc \
|
||||
google/protobuf/util/internal/default_value_objectwriter_test.cc \
|
||||
google/protobuf/util/internal/json_objectwriter_test.cc \
|
||||
google/protobuf/util/internal/json_stream_parser_test.cc \
|
||||
google/protobuf/util/internal/protostream_objectsource_test.cc \
|
||||
google/protobuf/util/internal/protostream_objectwriter_test.cc \
|
||||
google/protobuf/util/internal/type_info_test_helper.cc \
|
||||
google/protobuf/util/json_util_test.cc \
|
||||
google/protobuf/util/message_differencer_unittest.cc \
|
||||
google/protobuf/util/time_util_test.cc \
|
||||
google/protobuf/util/type_resolver_util_test.cc \
|
||||
$(COMMON_TEST_SOURCES)
|
||||
|
||||
|
||||
nodist_protobuf_test_SOURCES = $(protoc_outputs)
|
||||
|
||||
# Run cpp_unittest again with PROTOBUF_TEST_NO_DESCRIPTORS defined.
|
||||
protobuf_lazy_descriptor_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la \
|
||||
libprotoc.la \
|
||||
../gmock/gtest/lib/libgtest.la \
|
||||
../gmock/lib/libgmock.la \
|
||||
../gmock/lib/libgmock_main.la
|
||||
protobuf_lazy_descriptor_test_CPPFLAGS = -I$(srcdir)/../gmock/include \
|
||||
-I$(srcdir)/../gmock/gtest/include \
|
||||
-DPROTOBUF_TEST_NO_DESCRIPTORS
|
||||
protobuf_lazy_descriptor_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
|
||||
protobuf_lazy_descriptor_test_SOURCES = \
|
||||
google/protobuf/compiler/cpp/cpp_unittest.cc \
|
||||
$(COMMON_TEST_SOURCES)
|
||||
nodist_protobuf_lazy_descriptor_test_SOURCES = $(protoc_outputs)
|
||||
|
||||
COMMON_LITE_TEST_SOURCES = \
|
||||
google/protobuf/arena_test_util.cc \
|
||||
google/protobuf/arena_test_util.h \
|
||||
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
|
||||
|
||||
# Build lite_unittest separately, since it doesn't use gtest. It can't
|
||||
# depend on gtest because our internal version of gtest depend on proto
|
||||
# full runtime and we want to make sure this test builds without full
|
||||
# runtime.
|
||||
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 \
|
||||
$(COMMON_LITE_TEST_SOURCES)
|
||||
nodist_protobuf_lite_test_SOURCES = $(protoc_lite_outputs)
|
||||
|
||||
# lite_arena_unittest depends on gtest because teboring@ found that without
|
||||
# gtest when building the test internally our memory sanitizer doesn't detect
|
||||
# memory leaks (don't know why).
|
||||
protobuf_lite_arena_test_LDADD = $(PTHREAD_LIBS) libprotobuf-lite.la \
|
||||
../gmock/gtest/lib/libgtest.la \
|
||||
../gmock/lib/libgmock.la \
|
||||
../gmock/lib/libgmock_main.la
|
||||
protobuf_lite_arena_test_CPPFLAGS = -I$(srcdir)/../gmock/include \
|
||||
-I$(srcdir)/../gmock/gtest/include
|
||||
protobuf_lite_arena_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
|
||||
protobuf_lite_arena_test_SOURCES = \
|
||||
google/protobuf/lite_arena_unittest.cc \
|
||||
$(COMMON_LITE_TEST_SOURCES)
|
||||
nodist_protobuf_lite_arena_test_SOURCES = $(protoc_lite_outputs)
|
||||
|
||||
# Test plugin binary.
|
||||
test_plugin_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \
|
||||
../gmock/gtest/lib/libgtest.la
|
||||
test_plugin_CPPFLAGS = -I$(srcdir)/../gmock/gtest/include
|
||||
test_plugin_SOURCES = \
|
||||
google/protobuf/compiler/mock_code_generator.cc \
|
||||
google/protobuf/testing/file.cc \
|
||||
google/protobuf/testing/file.h \
|
||||
google/protobuf/compiler/test_plugin.cc
|
||||
|
||||
if HAVE_ZLIB
|
||||
zcgzip_LDADD = $(PTHREAD_LIBS) libprotobuf.la
|
||||
zcgzip_SOURCES = google/protobuf/testing/zcgzip.cc
|
||||
|
||||
zcgunzip_LDADD = $(PTHREAD_LIBS) libprotobuf.la
|
||||
zcgunzip_SOURCES = google/protobuf/testing/zcgunzip.cc
|
||||
endif
|
||||
|
||||
# This test target is to ensure all our public header files and generated
|
||||
# code is free from warnings. We have to be more pedantic about these
|
||||
# files because they are compiled by users with different compiler flags.
|
||||
no_warning_test.cc:
|
||||
echo "// Generated from Makefile.am" > no_warning_test.cc
|
||||
for FILE in $(nobase_include_HEADERS); do \
|
||||
if ! echo $${FILE} | grep "atomicops"; then \
|
||||
echo "#include <$${FILE}>" >> no_warning_test.cc; \
|
||||
fi \
|
||||
done
|
||||
echo "#include <gtest/gtest.h>" >> no_warning_test.cc
|
||||
echo "TEST(NoWarningTest, Empty) {}" >> no_warning_test.cc
|
||||
|
||||
no_warning_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la \
|
||||
../gmock/gtest/lib/libgtest.la \
|
||||
../gmock/gtest/lib/libgtest_main.la
|
||||
no_warning_test_CPPFLAGS = -I$(srcdir)/../gmock/gtest/include
|
||||
no_warning_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_DEF) $(ZLIB_DEF) \
|
||||
-Wall -Werror
|
||||
nodist_no_warning_test_SOURCES = no_warning_test.cc $(protoc_outputs)
|
||||
|
||||
TESTS = protobuf-test protobuf-lazy-descriptor-test protobuf-lite-test \
|
||||
google/protobuf/compiler/zip_output_unittest.sh $(GZTESTS) \
|
||||
protobuf-lite-arena-test no-warning-test
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,212 @@
|
||||
Protocol Buffers - Google's data interchange format
|
||||
===================================================
|
||||
|
||||
[](https://travis-ci.org/google/protobuf) [](https://ci.appveyor.com/project/protobuf/protobuf)
|
||||
|
||||
Copyright 2008 Google Inc.
|
||||
|
||||
https://developers.google.com/protocol-buffers/
|
||||
|
||||
C++ Installation - Unix
|
||||
-----------------------
|
||||
|
||||
To build protobuf from source, the following tools are needed:
|
||||
|
||||
* autoconf
|
||||
* automake
|
||||
* libtool
|
||||
* curl (used to download gmock)
|
||||
* make
|
||||
* g++
|
||||
* unzip
|
||||
|
||||
On Ubuntu, you can install them with:
|
||||
|
||||
$ sudo apt-get install autoconf automake libtool curl make g++ unzip
|
||||
|
||||
On other platforms, please use the corresponding package managing tool to
|
||||
install them before proceeding.
|
||||
|
||||
If you get the source from github, you need to generate the configure script
|
||||
first:
|
||||
|
||||
$ ./autogen.sh
|
||||
|
||||
This will download gmock source (which is used for C++ Protocol Buffer
|
||||
unit-tests) to the current directory and run automake, autoconf, etc.
|
||||
to generate the configure script and various template makefiles.
|
||||
|
||||
You can skip this step if you are using a release package (which already
|
||||
contains gmock and the configure script).
|
||||
|
||||
To build and install the C++ Protocol Buffer runtime and the Protocol
|
||||
Buffer compiler (protoc) execute the following:
|
||||
|
||||
$ ./configure
|
||||
$ make
|
||||
$ make check
|
||||
$ sudo make install
|
||||
$ sudo ldconfig # refresh shared library cache.
|
||||
|
||||
If "make check" fails, you can still install, but it is likely that
|
||||
some features of this library will not work correctly on your system.
|
||||
Proceed at your own risk.
|
||||
|
||||
For advanced usage information on configure and make, please refer to the
|
||||
autoconf documentation:
|
||||
|
||||
http://www.gnu.org/software/autoconf/manual/autoconf.html#Running-configure-Scripts
|
||||
|
||||
**Hint on install location**
|
||||
|
||||
By default, the package will be installed to /usr/local. However,
|
||||
on many platforms, /usr/local/lib is not part of LD_LIBRARY_PATH.
|
||||
You can add it, but it may be easier to just install to /usr
|
||||
instead. To do this, invoke configure as follows:
|
||||
|
||||
./configure --prefix=/usr
|
||||
|
||||
If you already built the package with a different prefix, make sure
|
||||
to run "make clean" before building again.
|
||||
|
||||
**Compiling dependent packages**
|
||||
|
||||
To compile a package that uses Protocol Buffers, you need to pass
|
||||
various flags to your compiler and linker. As of version 2.2.0,
|
||||
Protocol Buffers integrates with pkg-config to manage this. If you
|
||||
have pkg-config installed, then you can invoke it to get a list of
|
||||
flags like so:
|
||||
|
||||
pkg-config --cflags protobuf # print compiler flags
|
||||
pkg-config --libs protobuf # print linker flags
|
||||
pkg-config --cflags --libs protobuf # print both
|
||||
|
||||
For example:
|
||||
|
||||
c++ my_program.cc my_proto.pb.cc `pkg-config --cflags --libs protobuf`
|
||||
|
||||
Note that packages written prior to the 2.2.0 release of Protocol
|
||||
Buffers may not yet integrate with pkg-config to get flags, and may
|
||||
not pass the correct set of flags to correctly link against
|
||||
libprotobuf. If the package in question uses autoconf, you can
|
||||
often fix the problem by invoking its configure script like:
|
||||
|
||||
configure CXXFLAGS="$(pkg-config --cflags protobuf)" \
|
||||
LIBS="$(pkg-config --libs protobuf)"
|
||||
|
||||
This will force it to use the correct flags.
|
||||
|
||||
If you are writing an autoconf-based package that uses Protocol
|
||||
Buffers, you should probably use the PKG_CHECK_MODULES macro in your
|
||||
configure script like:
|
||||
|
||||
PKG_CHECK_MODULES([protobuf], [protobuf])
|
||||
|
||||
See the pkg-config man page for more info.
|
||||
|
||||
If you only want protobuf-lite, substitute "protobuf-lite" in place
|
||||
of "protobuf" in these examples.
|
||||
|
||||
**Note for Mac users**
|
||||
|
||||
For a Mac system, Unix tools are not available by default. You will first need
|
||||
to install Xcode from the Mac AppStore and then run the following command from
|
||||
a terminal:
|
||||
|
||||
$ sudo xcode-select --install
|
||||
|
||||
To install Unix tools, you can install "port" following the instructions at
|
||||
https://www.macports.org . This will reside in /opt/local/bin/port for most
|
||||
Mac installations.
|
||||
|
||||
$ sudo /opt/local/bin/port install autoconf automake libtool
|
||||
|
||||
Then follow the Unix instructions above.
|
||||
|
||||
**Note for cross-compiling**
|
||||
|
||||
The makefiles normally invoke the protoc executable that they just
|
||||
built in order to build tests. When cross-compiling, the protoc
|
||||
executable may not be executable on the host machine. In this case,
|
||||
you must build a copy of protoc for the host machine first, then use
|
||||
the --with-protoc option to tell configure to use it instead. For
|
||||
example:
|
||||
|
||||
./configure --with-protoc=protoc
|
||||
|
||||
This will use the installed protoc (found in your $PATH) instead of
|
||||
trying to execute the one built during the build process. You can
|
||||
also use an executable that hasn't been installed. For example, if
|
||||
you built the protobuf package for your host machine in ../host,
|
||||
you might do:
|
||||
|
||||
./configure --with-protoc=../host/src/protoc
|
||||
|
||||
Either way, you must make sure that the protoc executable you use
|
||||
has the same version as the protobuf source code you are trying to
|
||||
use it with.
|
||||
|
||||
**Note for Solaris users**
|
||||
|
||||
Solaris 10 x86 has a bug that will make linking fail, complaining
|
||||
about libstdc++.la being invalid. We have included a work-around
|
||||
in this package. To use the work-around, run configure as follows:
|
||||
|
||||
./configure LDFLAGS=-L$PWD/src/solaris
|
||||
|
||||
See src/solaris/libstdc++.la for more info on this bug.
|
||||
|
||||
**Note for HP C++ Tru64 users**
|
||||
|
||||
To compile invoke configure as follows:
|
||||
|
||||
./configure CXXFLAGS="-O -std ansi -ieee -D__USE_STD_IOSTREAM"
|
||||
|
||||
Also, you will need to use gmake instead of make.
|
||||
|
||||
**Note for AIX users**
|
||||
|
||||
Compile using the IBM xlC C++ compiler as follows:
|
||||
|
||||
./configure CXX=xlC
|
||||
|
||||
Also, you will need to use GNU `make` (`gmake`) instead of AIX `make`.
|
||||
|
||||
C++ Installation - Windows
|
||||
--------------------------
|
||||
|
||||
If you only need the protoc binary, you can download it from the release
|
||||
page:
|
||||
|
||||
https://github.com/google/protobuf/releases
|
||||
|
||||
In the downloads section, download the zip file protoc-$VERSION-win32.zip.
|
||||
It contains the protoc binary as well as public proto files of protobuf
|
||||
library.
|
||||
|
||||
To build from source using Microsoft Visual C++, see [cmake/README.md](../cmake/README.md).
|
||||
|
||||
To build from source using Cygwin or MinGW, follow the Unix installation
|
||||
instructions, above.
|
||||
|
||||
Binary Compatibility Warning
|
||||
----------------------------
|
||||
|
||||
Due to the nature of C++, it is unlikely that any two versions of the
|
||||
Protocol Buffers C++ runtime libraries will have compatible ABIs.
|
||||
That is, if you linked an executable against an older version of
|
||||
libprotobuf, it is unlikely to work with a newer version without
|
||||
re-compiling. This problem, when it occurs, will normally be detected
|
||||
immediately on startup of your app. Still, you may want to consider
|
||||
using static linkage. You can configure this package to install
|
||||
static libraries only using:
|
||||
|
||||
./configure --disable-shared
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The complete documentation for Protocol Buffers is available via the
|
||||
web at:
|
||||
|
||||
https://developers.google.com/protocol-buffers/
|
||||
@@ -0,0 +1,114 @@
|
||||
// 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/any.h>
|
||||
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
namespace {
|
||||
string GetTypeUrl(const Descriptor* message,
|
||||
const string& type_url_prefix) {
|
||||
if (!type_url_prefix.empty() &&
|
||||
type_url_prefix[type_url_prefix.size() - 1] == '/') {
|
||||
return type_url_prefix + message->full_name();
|
||||
} else {
|
||||
return type_url_prefix + "/" + message->full_name();
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
const char kAnyFullTypeName[] = "google.protobuf.Any";
|
||||
const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/";
|
||||
const char kTypeGoogleProdComPrefix[] = "type.googleprod.com/";
|
||||
|
||||
AnyMetadata::AnyMetadata(UrlType* type_url, ValueType* value)
|
||||
: type_url_(type_url), value_(value) {
|
||||
}
|
||||
|
||||
void AnyMetadata::PackFrom(const Message& message) {
|
||||
PackFrom(message, kTypeGoogleApisComPrefix);
|
||||
}
|
||||
|
||||
void AnyMetadata::PackFrom(const Message& message,
|
||||
const string& type_url_prefix) {
|
||||
type_url_->SetNoArena(&::google::protobuf::internal::GetEmptyString(),
|
||||
GetTypeUrl(message.GetDescriptor(), type_url_prefix));
|
||||
message.SerializeToString(value_->MutableNoArena(
|
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
|
||||
}
|
||||
|
||||
bool AnyMetadata::UnpackTo(Message* message) const {
|
||||
if (!InternalIs(message->GetDescriptor())) {
|
||||
return false;
|
||||
}
|
||||
return message->ParseFromString(value_->GetNoArena());
|
||||
}
|
||||
|
||||
bool AnyMetadata::InternalIs(const Descriptor* descriptor) const {
|
||||
const string type_url = type_url_->GetNoArena();
|
||||
string full_name;
|
||||
if (!ParseAnyTypeUrl(type_url, &full_name)) {
|
||||
return false;
|
||||
}
|
||||
return full_name == descriptor->full_name();
|
||||
}
|
||||
|
||||
bool ParseAnyTypeUrl(const string& type_url, string* full_type_name) {
|
||||
size_t pos = type_url.find_last_of("/");
|
||||
if (pos == string::npos || pos + 1 == type_url.size()) {
|
||||
return false;
|
||||
}
|
||||
*full_type_name = type_url.substr(pos + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool GetAnyFieldDescriptors(const Message& message,
|
||||
const FieldDescriptor** type_url_field,
|
||||
const FieldDescriptor** value_field) {
|
||||
const Descriptor* descriptor = message.GetDescriptor();
|
||||
if (descriptor->full_name() != kAnyFullTypeName) {
|
||||
return false;
|
||||
}
|
||||
*type_url_field = descriptor->FindFieldByNumber(1);
|
||||
*value_field = descriptor->FindFieldByNumber(2);
|
||||
return (*type_url_field != NULL &&
|
||||
(*type_url_field)->type() == FieldDescriptor::TYPE_STRING &&
|
||||
*value_field != NULL &&
|
||||
(*value_field)->type() == FieldDescriptor::TYPE_BYTES);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -0,0 +1,107 @@
|
||||
// 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_ANY_H__
|
||||
#define GOOGLE_PROTOBUF_ANY_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Helper class used to implement google::protobuf::Any.
|
||||
class LIBPROTOBUF_EXPORT AnyMetadata {
|
||||
typedef ArenaStringPtr UrlType;
|
||||
typedef ArenaStringPtr ValueType;
|
||||
public:
|
||||
// AnyMetadata does not take ownership of "type_url" and "value".
|
||||
AnyMetadata(UrlType* type_url, ValueType* value);
|
||||
|
||||
// Packs a message using the default type URL prefix: "type.googleapis.com".
|
||||
// The resulted type URL will be "type.googleapis.com/<message_full_name>".
|
||||
void PackFrom(const Message& message);
|
||||
// Packs a message using the given type URL prefix. The type URL will be
|
||||
// constructed by concatenating the message type's full name to the prefix
|
||||
// with an optional "/" separator if the prefix doesn't already end up "/".
|
||||
// For example, both PackFrom(message, "type.googleapis.com") and
|
||||
// PackFrom(message, "type.googleapis.com/") yield the same result type
|
||||
// URL: "type.googleapis.com/<message_full_name>".
|
||||
void PackFrom(const Message& message, const string& type_url_prefix);
|
||||
|
||||
// Unpacks the payload into the given message. Returns false if the message's
|
||||
// type doesn't match the type specified in the type URL (i.e., the full
|
||||
// name after the last "/" of the type URL doesn't match the message's actaul
|
||||
// full name) or parsing the payload has failed.
|
||||
bool UnpackTo(Message* message) const;
|
||||
|
||||
// Checks whether the type specified in the type URL matches the given type.
|
||||
// A type is consdiered matching if its full name matches the full name after
|
||||
// the last "/" in the type URL.
|
||||
template<typename T>
|
||||
bool Is() const {
|
||||
return InternalIs(T::default_instance().GetDescriptor());
|
||||
}
|
||||
|
||||
private:
|
||||
bool InternalIs(const Descriptor* message) const;
|
||||
|
||||
UrlType* type_url_;
|
||||
ValueType* value_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AnyMetadata);
|
||||
};
|
||||
|
||||
extern const char kAnyFullTypeName[]; // "google.protobuf.Any".
|
||||
extern const char kTypeGoogleApisComPrefix[]; // "type.googleapis.com/".
|
||||
extern const char kTypeGoogleProdComPrefix[]; // "type.googleprod.com/".
|
||||
|
||||
// Get the proto type name from Any::type_url value. For example, passing
|
||||
// "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in
|
||||
// *full_type_name. Returns false if type_url does not start with
|
||||
// "type.googleapis.com" or "type.googleprod.com".
|
||||
bool ParseAnyTypeUrl(const string& type_url, string* full_type_name);
|
||||
|
||||
// See if message is of type google.protobuf.Any, if so, return the descriptors
|
||||
// for "type_url" and "value" fields.
|
||||
bool GetAnyFieldDescriptors(const Message& message,
|
||||
const FieldDescriptor** type_url_field,
|
||||
const FieldDescriptor** value_field);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_ANY_H__
|
||||
@@ -0,0 +1,517 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/any.proto
|
||||
|
||||
#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
|
||||
#include <google/protobuf/any.pb.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class AnyDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<Any> {
|
||||
} _Any_default_instance_;
|
||||
|
||||
namespace protobuf_google_2fprotobuf_2fany_2eproto {
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
::google::protobuf::Metadata file_level_metadata[1];
|
||||
|
||||
} // namespace
|
||||
|
||||
const ::google::protobuf::uint32 TableStruct::offsets[] = {
|
||||
~0u, // no _has_bits_
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, _internal_metadata_),
|
||||
~0u, // no _extensions_
|
||||
~0u, // no _oneof_case_
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, type_url_),
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, value_),
|
||||
};
|
||||
|
||||
static const ::google::protobuf::internal::MigrationSchema schemas[] = {
|
||||
{ 0, -1, sizeof(Any)},
|
||||
};
|
||||
|
||||
static ::google::protobuf::Message const * const file_default_instances[] = {
|
||||
reinterpret_cast<const ::google::protobuf::Message*>(&_Any_default_instance_),
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
void protobuf_AssignDescriptors() {
|
||||
AddDescriptors();
|
||||
::google::protobuf::MessageFactory* factory = NULL;
|
||||
AssignDescriptors(
|
||||
"google/protobuf/any.proto", schemas, file_default_instances, TableStruct::offsets, factory,
|
||||
file_level_metadata, NULL, NULL);
|
||||
}
|
||||
|
||||
void protobuf_AssignDescriptorsOnce() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);
|
||||
}
|
||||
|
||||
void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
|
||||
void protobuf_RegisterTypes(const ::std::string&) {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void TableStruct::Shutdown() {
|
||||
_Any_default_instance_.Shutdown();
|
||||
delete file_level_metadata[0].reflection;
|
||||
}
|
||||
|
||||
void TableStruct::InitDefaultsImpl() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
::google::protobuf::internal::InitProtobufDefaults();
|
||||
_Any_default_instance_.DefaultConstruct();
|
||||
}
|
||||
|
||||
void InitDefaults() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);
|
||||
}
|
||||
void AddDescriptorsImpl() {
|
||||
InitDefaults();
|
||||
static const char descriptor[] = {
|
||||
"\n\031google/protobuf/any.proto\022\017google.prot"
|
||||
"obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002"
|
||||
" \001(\014Bo\n\023com.google.protobufB\010AnyProtoP\001Z"
|
||||
"%github.com/golang/protobuf/ptypes/any\242\002"
|
||||
"\003GPB\252\002\036Google.Protobuf.WellKnownTypesb\006p"
|
||||
"roto3"
|
||||
};
|
||||
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
|
||||
descriptor, 205);
|
||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
|
||||
"google/protobuf/any.proto", &protobuf_RegisterTypes);
|
||||
::google::protobuf::internal::OnShutdown(&TableStruct::Shutdown);
|
||||
}
|
||||
|
||||
void AddDescriptors() {
|
||||
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
|
||||
::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
|
||||
}
|
||||
// Force AddDescriptors() to be called at static initialization time.
|
||||
struct StaticDescriptorInitializer {
|
||||
StaticDescriptorInitializer() {
|
||||
AddDescriptors();
|
||||
}
|
||||
} static_descriptor_initializer;
|
||||
|
||||
} // namespace protobuf_google_2fprotobuf_2fany_2eproto
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
void Any::PackFrom(const ::google::protobuf::Message& message) {
|
||||
_any_metadata_.PackFrom(message);
|
||||
}
|
||||
|
||||
void Any::PackFrom(const ::google::protobuf::Message& message,
|
||||
const ::std::string& type_url_prefix) {
|
||||
_any_metadata_.PackFrom(message, type_url_prefix);
|
||||
}
|
||||
|
||||
bool Any::UnpackTo(::google::protobuf::Message* message) const {
|
||||
return _any_metadata_.UnpackTo(message);
|
||||
}
|
||||
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
const int Any::kTypeUrlFieldNumber;
|
||||
const int Any::kValueFieldNumber;
|
||||
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
|
||||
Any::Any()
|
||||
: ::google::protobuf::Message(), _internal_metadata_(NULL), _any_metadata_(&type_url_, &value_) {
|
||||
if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
|
||||
protobuf_google_2fprotobuf_2fany_2eproto::InitDefaults();
|
||||
}
|
||||
SharedCtor();
|
||||
// @@protoc_insertion_point(constructor:google.protobuf.Any)
|
||||
}
|
||||
Any::Any(const Any& from)
|
||||
: ::google::protobuf::Message(),
|
||||
_internal_metadata_(NULL),
|
||||
_cached_size_(0),
|
||||
_any_metadata_(&type_url_, &value_) {
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
if (from.type_url().size() > 0) {
|
||||
type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_url_);
|
||||
}
|
||||
value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
if (from.value().size() > 0) {
|
||||
value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.value_);
|
||||
}
|
||||
// @@protoc_insertion_point(copy_constructor:google.protobuf.Any)
|
||||
}
|
||||
|
||||
void Any::SharedCtor() {
|
||||
type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
_cached_size_ = 0;
|
||||
}
|
||||
|
||||
Any::~Any() {
|
||||
// @@protoc_insertion_point(destructor:google.protobuf.Any)
|
||||
SharedDtor();
|
||||
}
|
||||
|
||||
void Any::SharedDtor() {
|
||||
type_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
|
||||
void Any::SetCachedSize(int size) const {
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
}
|
||||
const ::google::protobuf::Descriptor* Any::descriptor() {
|
||||
protobuf_google_2fprotobuf_2fany_2eproto::protobuf_AssignDescriptorsOnce();
|
||||
return protobuf_google_2fprotobuf_2fany_2eproto::file_level_metadata[0].descriptor;
|
||||
}
|
||||
|
||||
const Any& Any::default_instance() {
|
||||
protobuf_google_2fprotobuf_2fany_2eproto::InitDefaults();
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
Any* Any::New(::google::protobuf::Arena* arena) const {
|
||||
Any* n = new Any;
|
||||
if (arena != NULL) {
|
||||
arena->Own(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void Any::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:google.protobuf.Any)
|
||||
type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
|
||||
bool Any::MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) {
|
||||
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
|
||||
::google::protobuf::uint32 tag;
|
||||
// @@protoc_insertion_point(parse_start:google.protobuf.Any)
|
||||
for (;;) {
|
||||
::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
|
||||
tag = p.first;
|
||||
if (!p.second) goto handle_unusual;
|
||||
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
|
||||
// string type_url = 1;
|
||||
case 1: {
|
||||
if (tag == 10u) {
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
|
||||
input, this->mutable_type_url()));
|
||||
DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->type_url().data(), this->type_url().length(),
|
||||
::google::protobuf::internal::WireFormatLite::PARSE,
|
||||
"google.protobuf.Any.type_url"));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
case 2: {
|
||||
if (tag == 18u) {
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
|
||||
input, this->mutable_value()));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
handle_unusual:
|
||||
if (tag == 0 ||
|
||||
::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
||||
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
|
||||
goto success;
|
||||
}
|
||||
DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
success:
|
||||
// @@protoc_insertion_point(parse_success:google.protobuf.Any)
|
||||
return true;
|
||||
failure:
|
||||
// @@protoc_insertion_point(parse_failure:google.protobuf.Any)
|
||||
return false;
|
||||
#undef DO_
|
||||
}
|
||||
|
||||
void Any::SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const {
|
||||
// @@protoc_insertion_point(serialize_start:google.protobuf.Any)
|
||||
// string type_url = 1;
|
||||
if (this->type_url().size() > 0) {
|
||||
::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->type_url().data(), this->type_url().length(),
|
||||
::google::protobuf::internal::WireFormatLite::SERIALIZE,
|
||||
"google.protobuf.Any.type_url");
|
||||
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
|
||||
1, this->type_url(), output);
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
if (this->value().size() > 0) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
|
||||
2, this->value(), output);
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(serialize_end:google.protobuf.Any)
|
||||
}
|
||||
|
||||
::google::protobuf::uint8* Any::InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* target) const {
|
||||
(void)deterministic; // Unused
|
||||
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Any)
|
||||
// string type_url = 1;
|
||||
if (this->type_url().size() > 0) {
|
||||
::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->type_url().data(), this->type_url().length(),
|
||||
::google::protobuf::internal::WireFormatLite::SERIALIZE,
|
||||
"google.protobuf.Any.type_url");
|
||||
target =
|
||||
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
|
||||
1, this->type_url(), target);
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
if (this->value().size() > 0) {
|
||||
target =
|
||||
::google::protobuf::internal::WireFormatLite::WriteBytesToArray(
|
||||
2, this->value(), target);
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Any)
|
||||
return target;
|
||||
}
|
||||
|
||||
size_t Any::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Any)
|
||||
size_t total_size = 0;
|
||||
|
||||
// string type_url = 1;
|
||||
if (this->type_url().size() > 0) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::StringSize(
|
||||
this->type_url());
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
if (this->value().size() > 0) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::BytesSize(
|
||||
this->value());
|
||||
}
|
||||
|
||||
int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = cached_size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
return total_size;
|
||||
}
|
||||
|
||||
void Any::MergeFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Any)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
const Any* source =
|
||||
::google::protobuf::internal::DynamicCastToGenerated<const Any>(
|
||||
&from);
|
||||
if (source == NULL) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Any)
|
||||
::google::protobuf::internal::ReflectionOps::Merge(from, this);
|
||||
} else {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Any)
|
||||
MergeFrom(*source);
|
||||
}
|
||||
}
|
||||
|
||||
void Any::MergeFrom(const Any& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Any)
|
||||
GOOGLE_DCHECK_NE(&from, this);
|
||||
_internal_metadata_.MergeFrom(from._internal_metadata_);
|
||||
if (from.type_url().size() > 0) {
|
||||
|
||||
type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_url_);
|
||||
}
|
||||
if (from.value().size() > 0) {
|
||||
|
||||
value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.value_);
|
||||
}
|
||||
}
|
||||
|
||||
void Any::CopyFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Any)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
void Any::CopyFrom(const Any& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Any)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
bool Any::IsInitialized() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Any::Swap(Any* other) {
|
||||
if (other == this) return;
|
||||
InternalSwap(other);
|
||||
}
|
||||
void Any::InternalSwap(Any* other) {
|
||||
type_url_.Swap(&other->type_url_);
|
||||
value_.Swap(&other->value_);
|
||||
std::swap(_cached_size_, other->_cached_size_);
|
||||
}
|
||||
|
||||
::google::protobuf::Metadata Any::GetMetadata() const {
|
||||
protobuf_google_2fprotobuf_2fany_2eproto::protobuf_AssignDescriptorsOnce();
|
||||
return protobuf_google_2fprotobuf_2fany_2eproto::file_level_metadata[0];
|
||||
}
|
||||
|
||||
#if PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
// Any
|
||||
|
||||
// string type_url = 1;
|
||||
void Any::clear_type_url() {
|
||||
type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
const ::std::string& Any::type_url() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Any.type_url)
|
||||
return type_url_.GetNoArena();
|
||||
}
|
||||
void Any::set_type_url(const ::std::string& value) {
|
||||
|
||||
type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Any.type_url)
|
||||
}
|
||||
#if LANG_CXX11
|
||||
void Any::set_type_url(::std::string&& value) {
|
||||
|
||||
type_url_.SetNoArena(
|
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited(), std::move(value));
|
||||
// @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.type_url)
|
||||
}
|
||||
#endif
|
||||
void Any::set_type_url(const char* value) {
|
||||
|
||||
type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:google.protobuf.Any.type_url)
|
||||
}
|
||||
void Any::set_type_url(const char* value, size_t size) {
|
||||
|
||||
type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.type_url)
|
||||
}
|
||||
::std::string* Any::mutable_type_url() {
|
||||
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url)
|
||||
return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
::std::string* Any::release_type_url() {
|
||||
// @@protoc_insertion_point(field_release:google.protobuf.Any.type_url)
|
||||
|
||||
return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
void Any::set_allocated_type_url(::std::string* type_url) {
|
||||
if (type_url != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_url);
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url)
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
void Any::clear_value() {
|
||||
value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
const ::std::string& Any::value() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Any.value)
|
||||
return value_.GetNoArena();
|
||||
}
|
||||
void Any::set_value(const ::std::string& value) {
|
||||
|
||||
value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Any.value)
|
||||
}
|
||||
#if LANG_CXX11
|
||||
void Any::set_value(::std::string&& value) {
|
||||
|
||||
value_.SetNoArena(
|
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited(), std::move(value));
|
||||
// @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.value)
|
||||
}
|
||||
#endif
|
||||
void Any::set_value(const char* value) {
|
||||
|
||||
value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:google.protobuf.Any.value)
|
||||
}
|
||||
void Any::set_value(const void* value, size_t size) {
|
||||
|
||||
value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.value)
|
||||
}
|
||||
::std::string* Any::mutable_value() {
|
||||
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.value)
|
||||
return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
::std::string* Any::release_value() {
|
||||
// @@protoc_insertion_point(field_release:google.protobuf.Any.value)
|
||||
|
||||
return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
void Any::set_allocated_value(::std::string* value) {
|
||||
if (value != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value)
|
||||
}
|
||||
|
||||
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
@@ -0,0 +1,294 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: google/protobuf/any.proto
|
||||
|
||||
#ifndef PROTOBUF_google_2fprotobuf_2fany_2eproto__INCLUDED
|
||||
#define PROTOBUF_google_2fprotobuf_2fany_2eproto__INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#if GOOGLE_PROTOBUF_VERSION < 3002000
|
||||
#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 3002000 < 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.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
|
||||
#include <google/protobuf/extension_set.h> // IWYU pragma: export
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
#include <google/protobuf/any.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class Any;
|
||||
class AnyDefaultTypeInternal;
|
||||
LIBPROTOBUF_EXPORT extern AnyDefaultTypeInternal _Any_default_instance_;
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace protobuf_google_2fprotobuf_2fany_2eproto {
|
||||
// Internal implementation detail -- do not call these.
|
||||
struct LIBPROTOBUF_EXPORT TableStruct {
|
||||
static const ::google::protobuf::uint32 offsets[];
|
||||
static void InitDefaultsImpl();
|
||||
static void Shutdown();
|
||||
};
|
||||
void LIBPROTOBUF_EXPORT AddDescriptors();
|
||||
void LIBPROTOBUF_EXPORT InitDefaults();
|
||||
} // namespace protobuf_google_2fprotobuf_2fany_2eproto
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Any) */ {
|
||||
public:
|
||||
Any();
|
||||
virtual ~Any();
|
||||
|
||||
Any(const Any& from);
|
||||
|
||||
inline Any& operator=(const Any& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const Any& default_instance();
|
||||
|
||||
static inline const Any* internal_default_instance() {
|
||||
return reinterpret_cast<const Any*>(
|
||||
&_Any_default_instance_);
|
||||
}
|
||||
|
||||
// implements Any -----------------------------------------------
|
||||
|
||||
void PackFrom(const ::google::protobuf::Message& message);
|
||||
void PackFrom(const ::google::protobuf::Message& message,
|
||||
const ::std::string& type_url_prefix);
|
||||
bool UnpackTo(::google::protobuf::Message* message) const;
|
||||
template<typename T> bool Is() const {
|
||||
return _any_metadata_.Is<T>();
|
||||
}
|
||||
|
||||
void Swap(Any* other);
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline Any* New() const PROTOBUF_FINAL { return New(NULL); }
|
||||
|
||||
Any* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
|
||||
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void CopyFrom(const Any& from);
|
||||
void MergeFrom(const Any& from);
|
||||
void Clear() PROTOBUF_FINAL;
|
||||
bool IsInitialized() const PROTOBUF_FINAL;
|
||||
|
||||
size_t ByteSizeLong() const PROTOBUF_FINAL;
|
||||
bool MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
|
||||
void SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
|
||||
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
|
||||
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output)
|
||||
const PROTOBUF_FINAL {
|
||||
return InternalSerializeWithCachedSizesToArray(
|
||||
::google::protobuf::io::CodedOutputStream::IsDefaultSerializationDeterministic(), output);
|
||||
}
|
||||
int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const PROTOBUF_FINAL;
|
||||
void InternalSwap(Any* other);
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return NULL;
|
||||
}
|
||||
inline void* MaybeArenaPtr() const {
|
||||
return NULL;
|
||||
}
|
||||
public:
|
||||
|
||||
::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// string type_url = 1;
|
||||
void clear_type_url();
|
||||
static const int kTypeUrlFieldNumber = 1;
|
||||
const ::std::string& type_url() const;
|
||||
void set_type_url(const ::std::string& value);
|
||||
#if LANG_CXX11
|
||||
void set_type_url(::std::string&& value);
|
||||
#endif
|
||||
void set_type_url(const char* value);
|
||||
void set_type_url(const char* value, size_t size);
|
||||
::std::string* mutable_type_url();
|
||||
::std::string* release_type_url();
|
||||
void set_allocated_type_url(::std::string* type_url);
|
||||
|
||||
// bytes value = 2;
|
||||
void clear_value();
|
||||
static const int kValueFieldNumber = 2;
|
||||
const ::std::string& value() const;
|
||||
void set_value(const ::std::string& value);
|
||||
#if LANG_CXX11
|
||||
void set_value(::std::string&& value);
|
||||
#endif
|
||||
void set_value(const char* value);
|
||||
void set_value(const void* value, size_t size);
|
||||
::std::string* mutable_value();
|
||||
::std::string* release_value();
|
||||
void set_allocated_value(::std::string* value);
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.Any)
|
||||
private:
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
|
||||
::google::protobuf::internal::ArenaStringPtr type_url_;
|
||||
::google::protobuf::internal::ArenaStringPtr value_;
|
||||
mutable int _cached_size_;
|
||||
::google::protobuf::internal::AnyMetadata _any_metadata_;
|
||||
friend struct LIBPROTOBUF_EXPORT protobuf_google_2fprotobuf_2fany_2eproto::TableStruct;
|
||||
};
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#if !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
// Any
|
||||
|
||||
// string type_url = 1;
|
||||
inline void Any::clear_type_url() {
|
||||
type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline const ::std::string& Any::type_url() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Any.type_url)
|
||||
return type_url_.GetNoArena();
|
||||
}
|
||||
inline void Any::set_type_url(const ::std::string& value) {
|
||||
|
||||
type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Any.type_url)
|
||||
}
|
||||
#if LANG_CXX11
|
||||
inline void Any::set_type_url(::std::string&& value) {
|
||||
|
||||
type_url_.SetNoArena(
|
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited(), std::move(value));
|
||||
// @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.type_url)
|
||||
}
|
||||
#endif
|
||||
inline void Any::set_type_url(const char* value) {
|
||||
|
||||
type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:google.protobuf.Any.type_url)
|
||||
}
|
||||
inline void Any::set_type_url(const char* value, size_t size) {
|
||||
|
||||
type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.type_url)
|
||||
}
|
||||
inline ::std::string* Any::mutable_type_url() {
|
||||
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url)
|
||||
return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline ::std::string* Any::release_type_url() {
|
||||
// @@protoc_insertion_point(field_release:google.protobuf.Any.type_url)
|
||||
|
||||
return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void Any::set_allocated_type_url(::std::string* type_url) {
|
||||
if (type_url != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_url);
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url)
|
||||
}
|
||||
|
||||
// bytes value = 2;
|
||||
inline void Any::clear_value() {
|
||||
value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline const ::std::string& Any::value() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Any.value)
|
||||
return value_.GetNoArena();
|
||||
}
|
||||
inline void Any::set_value(const ::std::string& value) {
|
||||
|
||||
value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.Any.value)
|
||||
}
|
||||
#if LANG_CXX11
|
||||
inline void Any::set_value(::std::string&& value) {
|
||||
|
||||
value_.SetNoArena(
|
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited(), std::move(value));
|
||||
// @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.value)
|
||||
}
|
||||
#endif
|
||||
inline void Any::set_value(const char* value) {
|
||||
|
||||
value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:google.protobuf.Any.value)
|
||||
}
|
||||
inline void Any::set_value(const void* value, size_t size) {
|
||||
|
||||
value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.value)
|
||||
}
|
||||
inline ::std::string* Any::mutable_value() {
|
||||
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.Any.value)
|
||||
return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline ::std::string* Any::release_value() {
|
||||
// @@protoc_insertion_point(field_release:google.protobuf.Any.value)
|
||||
|
||||
return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void Any::set_allocated_value(::std::string* value) {
|
||||
if (value != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value)
|
||||
}
|
||||
|
||||
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#endif // PROTOBUF_google_2fprotobuf_2fany_2eproto__INCLUDED
|
||||
@@ -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.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
option go_package = "github.com/golang/protobuf/ptypes/any";
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "AnyProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
|
||||
// `Any` contains an arbitrary serialized protocol buffer message along with a
|
||||
// URL that describes the type of the serialized message.
|
||||
//
|
||||
// Protobuf library provides support to pack/unpack Any values in the form
|
||||
// of utility functions or additional generated methods of the Any type.
|
||||
//
|
||||
// Example 1: Pack and unpack a message in C++.
|
||||
//
|
||||
// Foo foo = ...;
|
||||
// Any any;
|
||||
// any.PackFrom(foo);
|
||||
// ...
|
||||
// if (any.UnpackTo(&foo)) {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// Example 2: Pack and unpack a message in Java.
|
||||
//
|
||||
// Foo foo = ...;
|
||||
// Any any = Any.pack(foo);
|
||||
// ...
|
||||
// if (any.is(Foo.class)) {
|
||||
// foo = any.unpack(Foo.class);
|
||||
// }
|
||||
//
|
||||
// Example 3: Pack and unpack a message in Python.
|
||||
//
|
||||
// foo = Foo(...)
|
||||
// any = Any()
|
||||
// any.Pack(foo)
|
||||
// ...
|
||||
// if any.Is(Foo.DESCRIPTOR):
|
||||
// any.Unpack(foo)
|
||||
// ...
|
||||
//
|
||||
// The pack methods provided by protobuf library will by default use
|
||||
// 'type.googleapis.com/full.type.name' as the type URL and the unpack
|
||||
// methods only use the fully qualified type name after the last '/'
|
||||
// in the type URL, for example "foo.bar.com/x/y.z" will yield type
|
||||
// name "y.z".
|
||||
//
|
||||
//
|
||||
// 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 `@type`
|
||||
// field. Example (for message [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 protocol buffer message.
|
||||
//
|
||||
// For URLs which use the scheme `http`, `https`, or no scheme, the
|
||||
// following restrictions and interpretations apply:
|
||||
//
|
||||
// * If no scheme 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`).
|
||||
// The name should be in a canonical form (e.g., leading "." is
|
||||
// not accepted).
|
||||
// * An HTTP GET on the URL must yield a [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.)
|
||||
//
|
||||
// Schemes other than `http`, `https` (or the empty scheme) might be
|
||||
// used with implementation specific semantics.
|
||||
//
|
||||
string type_url = 1;
|
||||
|
||||
// Must be a valid serialized protocol buffer of the above specified type.
|
||||
bytes value = 2;
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
#include <google/protobuf/any_test.pb.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace {
|
||||
|
||||
TEST(AnyTest, TestPackAndUnpack) {
|
||||
protobuf_unittest::TestAny submessage;
|
||||
submessage.set_int32_value(12345);
|
||||
protobuf_unittest::TestAny message;
|
||||
message.mutable_any_value()->PackFrom(submessage);
|
||||
|
||||
string data = message.SerializeAsString();
|
||||
|
||||
ASSERT_TRUE(message.ParseFromString(data));
|
||||
EXPECT_TRUE(message.has_any_value());
|
||||
ASSERT_TRUE(message.any_value().UnpackTo(&submessage));
|
||||
EXPECT_EQ(12345, submessage.int32_value());
|
||||
}
|
||||
|
||||
TEST(AnyTest, TestPackAndUnpackAny) {
|
||||
// We can pack a Any message inside another Any message.
|
||||
protobuf_unittest::TestAny submessage;
|
||||
submessage.set_int32_value(12345);
|
||||
google::protobuf::Any any;
|
||||
any.PackFrom(submessage);
|
||||
protobuf_unittest::TestAny message;
|
||||
message.mutable_any_value()->PackFrom(any);
|
||||
|
||||
string data = message.SerializeAsString();
|
||||
|
||||
ASSERT_TRUE(message.ParseFromString(data));
|
||||
EXPECT_TRUE(message.has_any_value());
|
||||
ASSERT_TRUE(message.any_value().UnpackTo(&any));
|
||||
ASSERT_TRUE(any.UnpackTo(&submessage));
|
||||
EXPECT_EQ(12345, submessage.int32_value());
|
||||
}
|
||||
|
||||
TEST(AnyTest, TestIs) {
|
||||
protobuf_unittest::TestAny submessage;
|
||||
submessage.set_int32_value(12345);
|
||||
google::protobuf::Any any;
|
||||
any.PackFrom(submessage);
|
||||
ASSERT_TRUE(any.ParseFromString(any.SerializeAsString()));
|
||||
EXPECT_TRUE(any.Is<protobuf_unittest::TestAny>());
|
||||
EXPECT_FALSE(any.Is<google::protobuf::Any>());
|
||||
|
||||
protobuf_unittest::TestAny message;
|
||||
message.mutable_any_value()->PackFrom(any);
|
||||
ASSERT_TRUE(message.ParseFromString(message.SerializeAsString()));
|
||||
EXPECT_FALSE(message.any_value().Is<protobuf_unittest::TestAny>());
|
||||
EXPECT_TRUE(message.any_value().Is<google::protobuf::Any>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
@@ -0,0 +1,41 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package protobuf_unittest;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
|
||||
message TestAny {
|
||||
int32 int32_value = 1;
|
||||
google.protobuf.Any any_value = 2;
|
||||
repeated google.protobuf.Any repeated_any_value = 3;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,202 @@
|
||||
// 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 csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "ApiProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
option go_package = "google.golang.org/genproto/protobuf/api;api";
|
||||
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
string version = 4;
|
||||
|
||||
// Source context for the protocol buffer service represented by this
|
||||
// message.
|
||||
SourceContext source_context = 5;
|
||||
|
||||
// Included APIs. See [Mixin][].
|
||||
repeated Mixin mixins = 6;
|
||||
|
||||
// The source syntax of the service.
|
||||
Syntax syntax = 7;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
// The source syntax of this method.
|
||||
Syntax syntax = 7;
|
||||
}
|
||||
|
||||
// Declares an API to be included in this API. The including API must
|
||||
// redeclare all the methods from the included API, but documentation
|
||||
// and options are inherited as follows:
|
||||
//
|
||||
// - If after comment and whitespace stripping, the documentation
|
||||
// string of the redeclared method is empty, it will be inherited
|
||||
// from the original method.
|
||||
//
|
||||
// - Each annotation belonging to the service config (http,
|
||||
// visibility) which is not set in the redeclared method will be
|
||||
// inherited.
|
||||
//
|
||||
// - If an http annotation is inherited, the path pattern will be
|
||||
// modified as follows. Any version prefix will be replaced by the
|
||||
// version of the including API plus the [root][] path if specified.
|
||||
//
|
||||
// Example of a simple mixin:
|
||||
//
|
||||
// package google.acl.v1;
|
||||
// service AccessControl {
|
||||
// // Get the underlying ACL object.
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl) {
|
||||
// option (google.api.http).get = "/v1/{resource=**}:getAcl";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// package google.storage.v2;
|
||||
// service Storage {
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl);
|
||||
//
|
||||
// // Get a data record.
|
||||
// rpc GetData(GetDataRequest) returns (Data) {
|
||||
// option (google.api.http).get = "/v2/{resource=**}";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Example of a mixin configuration:
|
||||
//
|
||||
// apis:
|
||||
// - name: google.storage.v2.Storage
|
||||
// mixins:
|
||||
// - name: google.acl.v1.AccessControl
|
||||
//
|
||||
// The mixin construct implies that all methods in `AccessControl` are
|
||||
// also declared with same name and request/response types in
|
||||
// `Storage`. A documentation generator or annotation processor will
|
||||
// see the effective `Storage.GetAcl` method after inherting
|
||||
// documentation and annotations as follows:
|
||||
//
|
||||
// service Storage {
|
||||
// // Get the underlying ACL object.
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl) {
|
||||
// option (google.api.http).get = "/v2/{resource=**}:getAcl";
|
||||
// }
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// Note how the version in the path pattern changed from `v1` to `v2`.
|
||||
//
|
||||
// If the `root` field in the mixin is specified, it should be a
|
||||
// relative path under which inherited HTTP paths are placed. Example:
|
||||
//
|
||||
// apis:
|
||||
// - name: google.storage.v2.Storage
|
||||
// mixins:
|
||||
// - name: google.acl.v1.AccessControl
|
||||
// root: acls
|
||||
//
|
||||
// This implies the following inherited HTTP annotation:
|
||||
//
|
||||
// service Storage {
|
||||
// // Get the underlying ACL object.
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl) {
|
||||
// option (google.api.http).get = "/v2/acls/{resource=**}:getAcl";
|
||||
// }
|
||||
// ...
|
||||
// }
|
||||
message Mixin {
|
||||
// The fully qualified name of the API which is included.
|
||||
string name = 1;
|
||||
|
||||
// If non-empty specifies a path under which inherited HTTP paths
|
||||
// are rooted.
|
||||
string root = 2;
|
||||
}
|
||||
@@ -0,0 +1,315 @@
|
||||
// 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/arena.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#include <sanitizer/asan_interface.h>
|
||||
#endif // ADDRESS_SANITIZER
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
|
||||
google::protobuf::internal::SequenceNumber Arena::lifecycle_id_generator_;
|
||||
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
|
||||
Arena::ThreadCache& Arena::thread_cache() {
|
||||
static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ =
|
||||
new internal::ThreadLocalStorage<ThreadCache>();
|
||||
return *thread_cache_->Get();
|
||||
}
|
||||
#elif defined(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() {
|
||||
lifecycle_id_ = lifecycle_id_generator_.GetNext();
|
||||
blocks_ = 0;
|
||||
hint_ = 0;
|
||||
space_allocated_ = 0;
|
||||
owns_first_block_ = true;
|
||||
cleanup_list_ = 0;
|
||||
|
||||
if (options_.initial_block != NULL && options_.initial_block_size > 0) {
|
||||
GOOGLE_CHECK_GE(options_.initial_block_size, sizeof(Block))
|
||||
<< ": Initial block size too small for header.";
|
||||
|
||||
// Add first unowned block to list.
|
||||
Block* first_block = reinterpret_cast<Block*>(options_.initial_block);
|
||||
first_block->size = options_.initial_block_size;
|
||||
first_block->pos = kHeaderSize;
|
||||
first_block->next = NULL;
|
||||
// Thread which calls Init() owns the first block. This allows the
|
||||
// single-threaded case to allocate on the first block without taking any
|
||||
// locks.
|
||||
first_block->owner = &thread_cache();
|
||||
SetThreadCacheBlock(first_block);
|
||||
AddBlockInternal(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 = ResetInternal();
|
||||
|
||||
// Call the destruction hook
|
||||
if (options_.on_arena_destruction != NULL) {
|
||||
options_.on_arena_destruction(this, hooks_cookie_, space_allocated);
|
||||
}
|
||||
}
|
||||
|
||||
uint64 Arena::Reset() {
|
||||
// Invalidate any ThreadCaches pointing to any blocks we just destroyed.
|
||||
lifecycle_id_ = lifecycle_id_generator_.GetNext();
|
||||
return ResetInternal();
|
||||
}
|
||||
|
||||
uint64 Arena::ResetInternal() {
|
||||
CleanupList();
|
||||
uint64 space_allocated = FreeBlocks();
|
||||
|
||||
// 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,
|
||||
size_t start_block_size, size_t max_block_size) {
|
||||
size_t size;
|
||||
if (my_last_block != NULL) {
|
||||
// Double the current block size, up to a limit.
|
||||
size = 2 * (my_last_block->size);
|
||||
if (size > max_block_size) size = max_block_size;
|
||||
} else {
|
||||
size = start_block_size;
|
||||
}
|
||||
// Verify that n + kHeaderSize won't overflow.
|
||||
GOOGLE_CHECK_LE(n, std::numeric_limits<size_t>::max() - kHeaderSize);
|
||||
size = std::max(size, kHeaderSize + n);
|
||||
|
||||
Block* b = reinterpret_cast<Block*>(options_.block_alloc(size));
|
||||
b->pos = kHeaderSize + n;
|
||||
b->size = size;
|
||||
b->owner = me;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
// Poison the rest of the block for ASAN. It was unpoisoned by the underlying
|
||||
// malloc but it's not yet usable until we return it as part of an allocation.
|
||||
ASAN_POISON_MEMORY_REGION(
|
||||
reinterpret_cast<char*>(b) + b->pos, b->size - b->pos);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
return b;
|
||||
}
|
||||
|
||||
void Arena::AddBlock(Block* b) {
|
||||
MutexLock l(&blocks_lock_);
|
||||
AddBlockInternal(b);
|
||||
}
|
||||
|
||||
void Arena::AddBlockInternal(Block* b) {
|
||||
b->next = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
|
||||
google::protobuf::internal::Release_Store(&blocks_, reinterpret_cast<google::protobuf::internal::AtomicWord>(b));
|
||||
if (b->avail() != 0) {
|
||||
// Direct future allocations to this block.
|
||||
google::protobuf::internal::Release_Store(&hint_, reinterpret_cast<google::protobuf::internal::AtomicWord>(b));
|
||||
}
|
||||
space_allocated_ += b->size;
|
||||
}
|
||||
|
||||
void Arena::AddListNode(void* elem, void (*cleanup)(void*)) {
|
||||
Node* node = reinterpret_cast<Node*>(AllocateAligned(sizeof(Node)));
|
||||
node->elem = elem;
|
||||
node->cleanup = cleanup;
|
||||
node->next = reinterpret_cast<Node*>(
|
||||
google::protobuf::internal::NoBarrier_AtomicExchange(&cleanup_list_,
|
||||
reinterpret_cast<google::protobuf::internal::AtomicWord>(node)));
|
||||
}
|
||||
|
||||
void* Arena::AllocateAligned(const std::type_info* allocated, size_t n) {
|
||||
// Align n to next multiple of 8 (from Hacker's Delight, Chapter 3.)
|
||||
n = (n + 7) & -8;
|
||||
|
||||
// Monitor allocation if needed.
|
||||
if (GOOGLE_PREDICT_FALSE(hooks_cookie_ != NULL) &&
|
||||
options_.on_arena_allocation != NULL) {
|
||||
options_.on_arena_allocation(allocated, n, hooks_cookie_);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
return SlowAlloc(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();
|
||||
Block* b = reinterpret_cast<Block*>(google::protobuf::internal::Acquire_Load(&hint_));
|
||||
if (!b || b->owner != me || b->avail() < n) {
|
||||
return SlowAlloc(n);
|
||||
}
|
||||
return AllocFromBlock(b, n);
|
||||
}
|
||||
|
||||
void* Arena::AllocFromBlock(Block* b, size_t n) {
|
||||
size_t p = b->pos;
|
||||
b->pos = p + n;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_UNPOISON_MEMORY_REGION(reinterpret_cast<char*>(b) + p, n);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
return reinterpret_cast<char*>(b) + p;
|
||||
}
|
||||
|
||||
void* Arena::SlowAlloc(size_t n) {
|
||||
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) {
|
||||
SetThreadCacheBlock(b);
|
||||
google::protobuf::internal::NoBarrier_Store(&hint_, reinterpret_cast<google::protobuf::internal::AtomicWord>(b));
|
||||
return AllocFromBlock(b, n);
|
||||
}
|
||||
b = NewBlock(me, b, n, options_.start_block_size, options_.max_block_size);
|
||||
AddBlock(b);
|
||||
SetThreadCacheBlock(b);
|
||||
return reinterpret_cast<char*>(b) + kHeaderSize;
|
||||
}
|
||||
|
||||
uint64 Arena::SpaceAllocated() const {
|
||||
MutexLock l(&blocks_lock_);
|
||||
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->pos - kHeaderSize);
|
||||
b = b->next;
|
||||
}
|
||||
return space_used;
|
||||
}
|
||||
|
||||
std::pair<uint64, uint64> Arena::SpaceAllocatedAndUsed() const {
|
||||
return std::make_pair(SpaceAllocated(), SpaceUsed());
|
||||
}
|
||||
|
||||
uint64 Arena::FreeBlocks() {
|
||||
uint64 space_allocated = 0;
|
||||
Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
|
||||
Block* first_block = NULL;
|
||||
while (b != NULL) {
|
||||
space_allocated += (b->size);
|
||||
Block* next = b->next;
|
||||
if (next != NULL) {
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
// This memory was provided by the underlying allocator as unpoisoned, so
|
||||
// return it in an unpoisoned state.
|
||||
ASAN_UNPOISON_MEMORY_REGION(reinterpret_cast<char*>(b), b->size);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
options_.block_dealloc(b, b->size);
|
||||
} else {
|
||||
if (owns_first_block_) {
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
// This memory was provided by the underlying allocator as unpoisoned,
|
||||
// so return it in an unpoisoned state.
|
||||
ASAN_UNPOISON_MEMORY_REGION(reinterpret_cast<char*>(b), b->size);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
options_.block_dealloc(b, b->size);
|
||||
} else {
|
||||
// User passed in the first block, skip free'ing the memory.
|
||||
first_block = b;
|
||||
}
|
||||
}
|
||||
b = next;
|
||||
}
|
||||
blocks_ = 0;
|
||||
hint_ = 0;
|
||||
space_allocated_ = 0;
|
||||
if (!owns_first_block_) {
|
||||
// Make the first block that was passed in through ArenaOptions
|
||||
// available for reuse.
|
||||
first_block->pos = kHeaderSize;
|
||||
// Thread which calls Reset() owns the first block. This allows the
|
||||
// single-threaded case to allocate on the first block without taking any
|
||||
// locks.
|
||||
first_block->owner = &thread_cache();
|
||||
SetThreadCacheBlock(first_block);
|
||||
AddBlockInternal(first_block);
|
||||
}
|
||||
return space_allocated;
|
||||
}
|
||||
|
||||
void Arena::CleanupList() {
|
||||
Node* head =
|
||||
reinterpret_cast<Node*>(google::protobuf::internal::NoBarrier_Load(&cleanup_list_));
|
||||
while (head != NULL) {
|
||||
head->cleanup(head->elem);
|
||||
head = head->next;
|
||||
}
|
||||
cleanup_list_ = 0;
|
||||
}
|
||||
|
||||
Arena::Block* Arena::FindBlock(void* me) {
|
||||
// TODO(sanjay): We might want to keep a separate list with one
|
||||
// entry per thread.
|
||||
Block* b = reinterpret_cast<Block*>(google::protobuf::internal::Acquire_Load(&blocks_));
|
||||
while (b != NULL && b->owner != me) {
|
||||
b = b->next;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -0,0 +1,935 @@
|
||||
// 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 defines an Arena allocator for better allocation performance.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ARENA_H__
|
||||
#define GOOGLE_PROTOBUF_ARENA_H__
|
||||
|
||||
#include <limits>
|
||||
#ifdef max
|
||||
#undef max // Visual Studio defines this macro
|
||||
#endif
|
||||
#if __cplusplus >= 201103L
|
||||
#include <google/protobuf/stubs/type_traits.h>
|
||||
#endif
|
||||
#if defined(_MSC_VER) && !_HAS_EXCEPTIONS
|
||||
// Work around bugs in MSVC <typeinfo> header when _HAS_EXCEPTIONS=0.
|
||||
#include <exception>
|
||||
#include <typeinfo>
|
||||
namespace std {
|
||||
using type_info = ::type_info;
|
||||
}
|
||||
#else
|
||||
#include <typeinfo>
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/stubs/atomic_sequence_num.h>
|
||||
#include <google/protobuf/stubs/atomicops.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/mutex.h>
|
||||
#include <google/protobuf/stubs/type_traits.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class Arena; // defined below
|
||||
class Message; // message.h
|
||||
|
||||
namespace internal {
|
||||
class ArenaString; // arenastring.h
|
||||
class LazyField; // lazy_field.h
|
||||
|
||||
template<typename Type>
|
||||
class GenericTypeHandler; // repeated_field.h
|
||||
|
||||
// Templated cleanup methods.
|
||||
template<typename T> void arena_destruct_object(void* object) {
|
||||
reinterpret_cast<T*>(object)->~T();
|
||||
}
|
||||
template<typename T> void arena_delete_object(void* object) {
|
||||
delete reinterpret_cast<T*>(object);
|
||||
}
|
||||
inline void arena_free(void* object, size_t size) {
|
||||
#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation)
|
||||
::operator delete(object, size);
|
||||
#else
|
||||
(void)size;
|
||||
::operator delete(object);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// ArenaOptions provides optional additional parameters to arena construction
|
||||
// that control its block-allocation behavior.
|
||||
struct ArenaOptions {
|
||||
// This defines the size of the first block requested from the system malloc.
|
||||
// Subsequent block sizes will increase in a geometric series up to a maximum.
|
||||
size_t start_block_size;
|
||||
|
||||
// This defines the maximum block size requested from system malloc (unless an
|
||||
// individual arena allocation request occurs with a size larger than this
|
||||
// maximum). Requested block sizes increase up to this value, then remain
|
||||
// here.
|
||||
size_t max_block_size;
|
||||
|
||||
// An initial block of memory for the arena to use, or NULL for none. If
|
||||
// provided, the block must live at least as long as the arena itself. The
|
||||
// creator of the Arena retains ownership of the block after the Arena is
|
||||
// destroyed.
|
||||
char* initial_block;
|
||||
|
||||
// The size of the initial block, if provided.
|
||||
size_t initial_block_size;
|
||||
|
||||
// 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_info is promised to be static - its lifetime extends to
|
||||
// match program's lifetime (It is given by typeid operator).
|
||||
// Note: typeid(void) will be passed as allocated_type every time we
|
||||
// intentionally want to avoid monitoring an allocation. (i.e. internal
|
||||
// allocations for managing the arena)
|
||||
void (*on_arena_allocation)(const std::type_info* allocated_type,
|
||||
uint64 alloc_size, void* cookie);
|
||||
|
||||
ArenaOptions()
|
||||
: start_block_size(kDefaultStartBlockSize),
|
||||
max_block_size(kDefaultMaxBlockSize),
|
||||
initial_block(NULL),
|
||||
initial_block_size(0),
|
||||
block_alloc(&::operator new),
|
||||
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
|
||||
// arena allocator behavior -- see descriptions above.
|
||||
static const size_t kDefaultStartBlockSize = 256;
|
||||
static const size_t kDefaultMaxBlockSize = 8192;
|
||||
};
|
||||
|
||||
// Support for non-RTTI environments. (The metrics hooks API uses type
|
||||
// information.)
|
||||
#ifndef GOOGLE_PROTOBUF_NO_RTTI
|
||||
#define RTTI_TYPE_ID(type) (&typeid(type))
|
||||
#else
|
||||
#define RTTI_TYPE_ID(type) (NULL)
|
||||
#endif
|
||||
|
||||
// Arena allocator. Arena allocation replaces ordinary (heap-based) allocation
|
||||
// with new/delete, and improves performance by aggregating allocations into
|
||||
// larger blocks and freeing allocations all at once. Protocol messages are
|
||||
// allocated on an arena by using Arena::CreateMessage<T>(Arena*), below, and
|
||||
// are automatically freed when the arena is destroyed.
|
||||
//
|
||||
// This is a thread-safe implementation: multiple threads may allocate from the
|
||||
// arena concurrently. Destruction is not thread-safe and the destructing
|
||||
// thread must synchronize with users of the arena first.
|
||||
//
|
||||
// An arena provides two allocation interfaces: CreateMessage<T>, which works
|
||||
// for arena-enabled proto2 message types as well as other types that satisfy
|
||||
// the appropriate protocol (described below), and Create<T>, which works for
|
||||
// any arbitrary type T. CreateMessage<T> is better when the type T supports it,
|
||||
// because this interface (i) passes the arena pointer to the created object so
|
||||
// that its sub-objects and internal allocations can use the arena too, and (ii)
|
||||
// elides the object's destructor call when possible. Create<T> does not place
|
||||
// any special requirements on the type T, and will invoke the object's
|
||||
// destructor when the arena is destroyed.
|
||||
//
|
||||
// The arena message allocation protocol, required by CreateMessage<T>, is as
|
||||
// follows:
|
||||
//
|
||||
// - The type T must have (at least) two constructors: a constructor with no
|
||||
// arguments, called when a T is allocated on the heap; and a constructor with
|
||||
// a google::protobuf::Arena* argument, called when a T is allocated on an arena. If the
|
||||
// second constructor is called with a NULL arena pointer, it must be
|
||||
// equivalent to invoking the first (no-argument) constructor.
|
||||
//
|
||||
// - The type T must have a particular type trait: a nested type
|
||||
// |InternalArenaConstructable_|. This is usually a typedef to |void|. If no
|
||||
// such type trait exists, then the instantiation CreateMessage<T> will fail
|
||||
// to compile.
|
||||
//
|
||||
// - The type T *may* have the type trait |DestructorSkippable_|. If this type
|
||||
// trait is present in the type, then its destructor will not be called if and
|
||||
// only if it was passed a non-NULL arena pointer. If this type trait is not
|
||||
// present on the type, then its destructor is always called when the
|
||||
// containing arena is destroyed.
|
||||
//
|
||||
// - One- and two-user-argument forms of CreateMessage<T>() also exist that
|
||||
// forward these constructor arguments to T's constructor: for example,
|
||||
// CreateMessage<T>(Arena*, arg1, arg2) forwards to a constructor T(Arena*,
|
||||
// arg1, arg2).
|
||||
//
|
||||
// This protocol is implemented by all arena-enabled proto2 message classes as
|
||||
// well as RepeatedPtrField.
|
||||
//
|
||||
// Do NOT subclass Arena. This class will be marked as final when C++11 is
|
||||
// enabled.
|
||||
class LIBPROTOBUF_EXPORT Arena {
|
||||
public:
|
||||
// Arena constructor taking custom options. See ArenaOptions below for
|
||||
// descriptions of the options available.
|
||||
explicit Arena(const ArenaOptions& options) : options_(options) {
|
||||
Init();
|
||||
}
|
||||
|
||||
// Default constructor with sensible default options, tuned for average
|
||||
// use-cases.
|
||||
Arena() {
|
||||
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();
|
||||
|
||||
// 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
|
||||
// defined in a .proto file with cc_enable_arenas set to true, otherwise a
|
||||
// compilation error will occur.
|
||||
//
|
||||
// RepeatedField and RepeatedPtrField may also be instantiated directly on an
|
||||
// arena with this method.
|
||||
//
|
||||
// This function also accepts any type T that satisfies the arena message
|
||||
// allocation protocol, documented above.
|
||||
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
static T* CreateMessage(::google::protobuf::Arena* arena) {
|
||||
if (arena == NULL) {
|
||||
return new T;
|
||||
} else {
|
||||
return arena->CreateMessageInternal<T>(static_cast<T*>(0));
|
||||
}
|
||||
}
|
||||
|
||||
// One-argument form of CreateMessage. This is useful for constructing objects
|
||||
// that implement the arena message construction protocol described above but
|
||||
// take additional constructor arguments.
|
||||
template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
static T* CreateMessage(::google::protobuf::Arena* arena, const Arg& arg) {
|
||||
if (arena == NULL) {
|
||||
return new T(NULL, arg);
|
||||
} else {
|
||||
return arena->CreateMessageInternal<T>(static_cast<T*>(0),
|
||||
arg);
|
||||
}
|
||||
}
|
||||
|
||||
// Two-argument form of CreateMessage. This is useful for constructing objects
|
||||
// that implement the arena message construction protocol described above but
|
||||
// take additional constructor arguments.
|
||||
template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
static T* CreateMessage(::google::protobuf::Arena* arena,
|
||||
const Arg1& arg1,
|
||||
const Arg2& arg2) {
|
||||
if (arena == NULL) {
|
||||
return new T(NULL, arg1, arg2);
|
||||
} else {
|
||||
return arena->CreateMessageInternal<T>(static_cast<T*>(0),
|
||||
arg1, arg2);
|
||||
}
|
||||
}
|
||||
|
||||
// API to create any objects on the arena. Note that only the object will
|
||||
// be created on the arena; the underlying ptrs (in case of a proto2 message)
|
||||
// will be still heap allocated. Proto messages should usually be allocated
|
||||
// with CreateMessage<T>() instead.
|
||||
//
|
||||
// Note that even if T satisfies the arena message construction protocol
|
||||
// (InternalArenaConstructable_ trait and optional DestructorSkippable_
|
||||
// trait), as described above, this function does not follow the protocol;
|
||||
// instead, it treats T as a black-box type, just as if it did not have these
|
||||
// traits. Specifically, T's constructor arguments will always be only those
|
||||
// passed to Create<T>() -- no additional arena pointer is implicitly added.
|
||||
// Furthermore, the destructor will always be called at arena destruction time
|
||||
// (unless the destructor is trivial). Hence, from T's point of view, it is as
|
||||
// if the object were allocated on the heap (except that the underlying memory
|
||||
// is obtained from the arena).
|
||||
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
static T* Create(::google::protobuf::Arena* arena) {
|
||||
if (arena == NULL) {
|
||||
return new T();
|
||||
} else {
|
||||
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value);
|
||||
}
|
||||
}
|
||||
|
||||
// Version of the above with one constructor argument for the created object.
|
||||
template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
static T* Create(::google::protobuf::Arena* arena, const Arg& arg) {
|
||||
if (arena == NULL) {
|
||||
return new T(arg);
|
||||
} else {
|
||||
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
|
||||
arg);
|
||||
}
|
||||
}
|
||||
|
||||
// Version of the above with two constructor arguments for the created object.
|
||||
template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
static T* Create(::google::protobuf::Arena* arena, const Arg1& arg1, const Arg2& arg2) {
|
||||
if (arena == NULL) {
|
||||
return new T(arg1, arg2);
|
||||
} else {
|
||||
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
|
||||
arg1, arg2);
|
||||
}
|
||||
}
|
||||
|
||||
// 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>(google::protobuf::internal::has_trivial_destructor<T>::value,
|
||||
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>(google::protobuf::internal::has_trivial_destructor<T>::value,
|
||||
arg1, arg2, arg3, arg4);
|
||||
}
|
||||
}
|
||||
|
||||
// Version of the above with five constructor arguments for the created
|
||||
// object.
|
||||
template <typename T, typename Arg1, typename Arg2, typename Arg3,
|
||||
typename Arg4, typename Arg5>
|
||||
GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
|
||||
const Arg1& arg1, const Arg2& arg2,
|
||||
const Arg3& arg3, const Arg4& arg4,
|
||||
const Arg5& arg5) {
|
||||
if (arena == NULL) {
|
||||
return new T(arg1, arg2, arg3, arg4, arg5);
|
||||
} else {
|
||||
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
|
||||
arg1, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
}
|
||||
|
||||
// Version of the above with six constructor arguments for the created
|
||||
// object.
|
||||
template <typename T, typename Arg1, typename Arg2, typename Arg3,
|
||||
typename Arg4, typename Arg5, typename Arg6>
|
||||
GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
|
||||
const Arg1& arg1, const Arg2& arg2,
|
||||
const Arg3& arg3, const Arg4& arg4,
|
||||
const Arg5& arg5, const Arg6& arg6) {
|
||||
if (arena == NULL) {
|
||||
return new T(arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
} else {
|
||||
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
|
||||
arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
}
|
||||
}
|
||||
|
||||
// Version of the above with seven constructor arguments for the created
|
||||
// object.
|
||||
template <typename T, typename Arg1, typename Arg2, typename Arg3,
|
||||
typename Arg4, typename Arg5, typename Arg6, typename Arg7>
|
||||
GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
|
||||
const Arg1& arg1, const Arg2& arg2,
|
||||
const Arg3& arg3, const Arg4& arg4,
|
||||
const Arg5& arg5, const Arg6& arg6,
|
||||
const Arg7& arg7) {
|
||||
if (arena == NULL) {
|
||||
return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
|
||||
} else {
|
||||
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
|
||||
arg1, arg2, arg3, arg4, arg5, arg6, arg7);
|
||||
}
|
||||
}
|
||||
|
||||
// Version of the above with eight constructor arguments for the created
|
||||
// object.
|
||||
template <typename T, typename Arg1, typename Arg2, typename Arg3,
|
||||
typename Arg4, typename Arg5, typename Arg6, typename Arg7,
|
||||
typename Arg8>
|
||||
GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
|
||||
const Arg1& arg1, const Arg2& arg2,
|
||||
const Arg3& arg3, const Arg4& arg4,
|
||||
const Arg5& arg5, const Arg6& arg6,
|
||||
const Arg7& arg7, const Arg8& arg8) {
|
||||
if (arena == NULL) {
|
||||
return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
|
||||
} else {
|
||||
return arena->CreateInternal<T>(
|
||||
google::protobuf::internal::has_trivial_destructor<T>::value,
|
||||
arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
|
||||
}
|
||||
}
|
||||
|
||||
// Create an array of object type T on the arena *without* invoking the
|
||||
// constructor of T. If `arena` is null, then the return value should be freed
|
||||
// with `delete[] x;` (or `::operator delete[](x);`).
|
||||
// To ensure safe uses, this function checks at compile time
|
||||
// (when compiled as C++11) that T is trivially default-constructible and
|
||||
// trivially destructible.
|
||||
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
static T* CreateArray(::google::protobuf::Arena* arena, size_t num_elements) {
|
||||
GOOGLE_CHECK_LE(num_elements,
|
||||
std::numeric_limits<size_t>::max() / sizeof(T))
|
||||
<< "Requested size is too large to fit into size_t.";
|
||||
if (arena == NULL) {
|
||||
return static_cast<T*>(::operator new[](num_elements * sizeof(T)));
|
||||
} else {
|
||||
return arena->CreateInternalRawArray<T>(num_elements);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the total space allocated by the arena, which is the sum of the
|
||||
// sizes of the underlying blocks. This method is relatively fast; a counter
|
||||
// is kept as blocks are allocated.
|
||||
uint64 SpaceAllocated() const;
|
||||
// Returns the total space used by the arena. Similar to SpaceAllocated but
|
||||
// does not include free space and block overhead. The total space returned
|
||||
// may not include space used by other threads executing concurrently with
|
||||
// the call to this method.
|
||||
GOOGLE_ATTRIBUTE_NOINLINE uint64 SpaceUsed() const;
|
||||
// DEPRECATED. Please use SpaceAllocated() and SpaceUsed().
|
||||
//
|
||||
// Combines SpaceAllocated and SpaceUsed. Returns a pair of
|
||||
// <space_allocated, space_used>.
|
||||
GOOGLE_ATTRIBUTE_NOINLINE std::pair<uint64, uint64> SpaceAllocatedAndUsed() const;
|
||||
|
||||
// Frees all storage allocated by this arena after calling destructors
|
||||
// registered with OwnDestructor() and freeing objects registered with Own().
|
||||
// Any objects allocated on this arena are unusable after this call. It also
|
||||
// returns the total space used by the arena which is the sums of the sizes
|
||||
// of the allocated blocks. This method is not thread-safe.
|
||||
GOOGLE_ATTRIBUTE_NOINLINE uint64 Reset();
|
||||
|
||||
// Adds |object| to a list of heap-allocated objects to be freed with |delete|
|
||||
// when the arena is destroyed or reset.
|
||||
template <typename T> GOOGLE_ATTRIBUTE_NOINLINE
|
||||
void Own(T* object) {
|
||||
OwnInternal(object, google::protobuf::internal::is_convertible<T*, ::google::protobuf::Message*>());
|
||||
}
|
||||
|
||||
// Adds |object| to a list of objects whose destructors will be manually
|
||||
// called when the arena is destroyed or reset. This differs from Own() in
|
||||
// that it does not free the underlying memory with |delete|; hence, it is
|
||||
// normally only used for objects that are placement-newed into
|
||||
// arena-allocated memory.
|
||||
template <typename T> GOOGLE_ATTRIBUTE_NOINLINE
|
||||
void OwnDestructor(T* object) {
|
||||
if (object != NULL) {
|
||||
AddListNode(object, &internal::arena_destruct_object<T>);
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a custom member function on an object to the list of destructors that
|
||||
// will be manually called when the arena is destroyed or reset. This differs
|
||||
// from OwnDestructor() in that any member function may be specified, not only
|
||||
// the class destructor.
|
||||
GOOGLE_ATTRIBUTE_NOINLINE void OwnCustomDestructor(void* object,
|
||||
void (*destruct)(void*)) {
|
||||
AddListNode(object, destruct);
|
||||
}
|
||||
|
||||
// Retrieves the arena associated with |value| if |value| is an arena-capable
|
||||
// message, or NULL otherwise. This differs from value->GetArena() in that the
|
||||
// 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 ::google::protobuf::Arena* GetArena(const T* value) {
|
||||
return GetArenaInternal(value, static_cast<T*>(0));
|
||||
}
|
||||
|
||||
private:
|
||||
struct InternalIsArenaConstructableHelper {
|
||||
template<typename U>
|
||||
static char ArenaConstructable(
|
||||
const typename U::InternalArenaConstructable_*);
|
||||
template<typename U>
|
||||
static double ArenaConstructable(...);
|
||||
};
|
||||
|
||||
public:
|
||||
// Helper typetrait that indicates support for arenas in a type T at compile
|
||||
// time. This is public only to allow construction of higher-level templated
|
||||
// utilities. is_arena_constructable<T>::value is true if the message type T
|
||||
// has arena support enabled, and false otherwise.
|
||||
//
|
||||
// This is inside Arena because only Arena has the friend relationships
|
||||
// necessary to see the underlying generated code traits.
|
||||
template <typename T>
|
||||
struct is_arena_constructable
|
||||
: public google::protobuf::internal::integral_constant<
|
||||
bool, sizeof(InternalIsArenaConstructableHelper::ArenaConstructable<
|
||||
const T>(static_cast<const T*>(0))) == sizeof(char)> {
|
||||
};
|
||||
|
||||
private:
|
||||
// Blocks are variable length malloc-ed objects. The following structure
|
||||
// describes the common header for all blocks.
|
||||
struct Block {
|
||||
void* owner; // &ThreadCache of thread that owns this block, or
|
||||
// &this->owner if not yet owned by a thread.
|
||||
Block* next; // Next block in arena (may have different owner)
|
||||
// ((char*) &block) + pos is next available byte. It is always
|
||||
// aligned at a multiple of 8 bytes.
|
||||
size_t pos;
|
||||
size_t size; // total size of the block.
|
||||
GOOGLE_ATTRIBUTE_ALWAYS_INLINE size_t avail() const { return size - pos; }
|
||||
// data follows
|
||||
};
|
||||
|
||||
template<typename Type> friend class ::google::protobuf::internal::GenericTypeHandler;
|
||||
friend class MockArena; // For unit-testing.
|
||||
friend class internal::ArenaString; // For AllocateAligned.
|
||||
friend class internal::LazyField; // For CreateMaybeMessage.
|
||||
|
||||
struct ThreadCache {
|
||||
// The ThreadCache is considered valid as long as this matches the
|
||||
// lifecycle_id of the arena being used.
|
||||
int64 last_lifecycle_id_seen;
|
||||
Block* last_block_used_;
|
||||
};
|
||||
|
||||
static const size_t kHeaderSize = sizeof(Block);
|
||||
static google::protobuf::internal::SequenceNumber lifecycle_id_generator_;
|
||||
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
|
||||
// Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread
|
||||
// local storage class we implemented.
|
||||
// iOS also does not support the GOOGLE_THREAD_LOCAL keyword.
|
||||
static ThreadCache& thread_cache();
|
||||
#elif defined(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 message type when created
|
||||
// with CreateMessage. This is mainly to skip proto2/proto1 message objects
|
||||
// with cc_enable_arenas=true from being part of the delete list. Also, note,
|
||||
// compiler will optimize out the branch in CreateInternal<T>.
|
||||
template<typename T>
|
||||
static inline bool SkipDeleteList(typename T::DestructorSkippable_*) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// For message objects that don't have the DestructorSkippable_ trait, we
|
||||
// always add to the delete list.
|
||||
template<typename T>
|
||||
static inline bool SkipDeleteList(...) {
|
||||
return google::protobuf::internal::has_trivial_destructor<T>::value;
|
||||
}
|
||||
|
||||
private:
|
||||
struct InternalIsDestructorSkippableHelper {
|
||||
template<typename U>
|
||||
static char DestructorSkippable(
|
||||
const typename U::DestructorSkippable_*);
|
||||
template<typename U>
|
||||
static double DestructorSkippable(...);
|
||||
};
|
||||
|
||||
public:
|
||||
// Helper typetrait that indicates whether the desctructor of type T should be
|
||||
// called when arena is destroyed at compile time. This is only to allow
|
||||
// construction of higher-level templated utilities.
|
||||
// is_destructor_skippable<T>::value is true if the destructor of the message
|
||||
// type T should not be called when arena is destroyed or false otherwise.
|
||||
// This is inside Arena because only Arena has the friend relationships
|
||||
// necessary to see the underlying generated code traits.
|
||||
template<typename T>
|
||||
struct is_destructor_skippable
|
||||
: public google::protobuf::internal::integral_constant<
|
||||
bool,
|
||||
sizeof(InternalIsDestructorSkippableHelper::DestructorSkippable<
|
||||
const T>(static_cast<const T*>(0))) == sizeof(char) ||
|
||||
google::protobuf::internal::has_trivial_destructor<T>::value> {};
|
||||
|
||||
private:
|
||||
// CreateMessage<T> requires that T supports arenas, but this private method
|
||||
// works whether or not T supports arenas. These are not exposed to user code
|
||||
// as it can cause confusing API usages, and end up having double free in
|
||||
// user code. These are used only internally from LazyField and Repeated
|
||||
// fields, since they are designed to work in all mode combinations.
|
||||
template<typename Msg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
static Msg* CreateMaybeMessage(
|
||||
Arena* arena, typename Msg::InternalArenaConstructable_*) {
|
||||
return CreateMessage<Msg>(arena);
|
||||
}
|
||||
|
||||
template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
static T* CreateMaybeMessage(Arena* 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
|
||||
T* CreateInternalRawArray(size_t num_elements) {
|
||||
GOOGLE_CHECK_LE(num_elements,
|
||||
std::numeric_limits<size_t>::max() / sizeof(T))
|
||||
<< "Requested size is too large to fit into size_t.";
|
||||
return static_cast<T*>(
|
||||
AllocateAligned(RTTI_TYPE_ID(T), sizeof(T) * num_elements));
|
||||
}
|
||||
|
||||
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
T* CreateInternal(bool skip_explicit_ownership) {
|
||||
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T();
|
||||
if (!skip_explicit_ownership) {
|
||||
AddListNode(t, &internal::arena_destruct_object<T>);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
T* CreateInternal(bool skip_explicit_ownership, const Arg& arg) {
|
||||
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg);
|
||||
if (!skip_explicit_ownership) {
|
||||
AddListNode(t, &internal::arena_destruct_object<T>);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
T* CreateInternal(
|
||||
bool skip_explicit_ownership, const Arg1& arg1, const Arg2& arg2) {
|
||||
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg1, arg2);
|
||||
if (!skip_explicit_ownership) {
|
||||
AddListNode(t, &internal::arena_destruct_object<T>);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
template <typename T, typename Arg1, typename Arg2, typename Arg3>
|
||||
GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
|
||||
const Arg1& arg1,
|
||||
const Arg2& arg2,
|
||||
const Arg3& arg3) {
|
||||
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), 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 T* CreateInternal(bool skip_explicit_ownership,
|
||||
const Arg1& arg1,
|
||||
const Arg2& arg2,
|
||||
const Arg3& arg3,
|
||||
const Arg4& arg4) {
|
||||
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
|
||||
T(arg1, arg2, arg3, arg4);
|
||||
if (!skip_explicit_ownership) {
|
||||
AddListNode(t, &internal::arena_destruct_object<T>);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
template <typename T, typename Arg1, typename Arg2, typename Arg3,
|
||||
typename Arg4, typename Arg5>
|
||||
GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
|
||||
const Arg1& arg1,
|
||||
const Arg2& arg2,
|
||||
const Arg3& arg3,
|
||||
const Arg4& arg4,
|
||||
const Arg5& arg5) {
|
||||
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
|
||||
T(arg1, arg2, arg3, arg4, arg5);
|
||||
if (!skip_explicit_ownership) {
|
||||
AddListNode(t, &internal::arena_destruct_object<T>);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
template <typename T, typename Arg1, typename Arg2, typename Arg3,
|
||||
typename Arg4, typename Arg5, typename Arg6>
|
||||
GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
|
||||
const Arg1& arg1,
|
||||
const Arg2& arg2,
|
||||
const Arg3& arg3,
|
||||
const Arg4& arg4,
|
||||
const Arg5& arg5,
|
||||
const Arg6& arg6) {
|
||||
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
|
||||
T(arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
if (!skip_explicit_ownership) {
|
||||
AddListNode(t, &internal::arena_destruct_object<T>);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
template <typename T, typename Arg1, typename Arg2, typename Arg3,
|
||||
typename Arg4, typename Arg5, typename Arg6, typename Arg7>
|
||||
GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
|
||||
const Arg1& arg1,
|
||||
const Arg2& arg2,
|
||||
const Arg3& arg3,
|
||||
const Arg4& arg4,
|
||||
const Arg5& arg5,
|
||||
const Arg6& arg6,
|
||||
const Arg7& arg7) {
|
||||
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
|
||||
T(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
|
||||
if (!skip_explicit_ownership) {
|
||||
AddListNode(t, &internal::arena_destruct_object<T>);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
template <typename T, typename Arg1, typename Arg2, typename Arg3,
|
||||
typename Arg4, typename Arg5, typename Arg6, typename Arg7,
|
||||
typename Arg8>
|
||||
GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
|
||||
const Arg1& arg1,
|
||||
const Arg2& arg2,
|
||||
const Arg3& arg3,
|
||||
const Arg4& arg4,
|
||||
const Arg5& arg5,
|
||||
const Arg6& arg6,
|
||||
const Arg7& arg7,
|
||||
const Arg8& arg8) {
|
||||
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
|
||||
T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
|
||||
if (!skip_explicit_ownership) {
|
||||
AddListNode(t, &internal::arena_destruct_object<T>);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
T* CreateMessageInternal(typename T::InternalArenaConstructable_*) {
|
||||
return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
|
||||
this);
|
||||
}
|
||||
|
||||
template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
|
||||
const Arg& arg) {
|
||||
return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
|
||||
this, arg);
|
||||
}
|
||||
|
||||
template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
|
||||
const Arg1& arg1, const Arg2& arg2) {
|
||||
return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
|
||||
this, arg1, arg2);
|
||||
}
|
||||
|
||||
// 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,
|
||||
typename is_arena_constructable<T>::type());
|
||||
RegisterDestructorInternal(ptr, arena,
|
||||
typename is_destructor_skippable<T>::type());
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void RegisterDestructorInternal(
|
||||
T* ptr, Arena* arena, google::protobuf::internal::true_type) {}
|
||||
template <typename T>
|
||||
static void RegisterDestructorInternal(
|
||||
T* ptr, Arena* arena, google::protobuf::internal::false_type) {
|
||||
arena->OwnDestructor(ptr);
|
||||
}
|
||||
|
||||
// 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
|
||||
// all template instantiations to one for generic Message reduces code size,
|
||||
// using the virtual destructor instead.
|
||||
template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
void OwnInternal(T* object, google::protobuf::internal::true_type) {
|
||||
if (object != NULL) {
|
||||
AddListNode(object, &internal::arena_delete_object< ::google::protobuf::Message >);
|
||||
}
|
||||
}
|
||||
template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
void OwnInternal(T* object, google::protobuf::internal::false_type) {
|
||||
if (object != NULL) {
|
||||
AddListNode(object, &internal::arena_delete_object<T>);
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation for GetArena(). Only message objects with
|
||||
// InternalArenaConstructable_ tags can be associated with an arena, and such
|
||||
// objects must implement a GetArenaNoVirtual() method.
|
||||
template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
static ::google::protobuf::Arena* GetArenaInternal(
|
||||
const T* value, typename T::InternalArenaConstructable_*) {
|
||||
return value->GetArenaNoVirtual();
|
||||
}
|
||||
|
||||
template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
static ::google::protobuf::Arena* GetArenaInternal(const T* value, ...) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Allocate and also optionally call on_arena_allocation callback with the
|
||||
// allocated type info when the hooks are in place in ArenaOptions and
|
||||
// the cookie is not null.
|
||||
void* AllocateAligned(const std::type_info* allocated, size_t n);
|
||||
|
||||
// Allocate an internal allocation, avoiding optional typed monitoring.
|
||||
GOOGLE_ATTRIBUTE_ALWAYS_INLINE void* AllocateAligned(size_t n) {
|
||||
return AllocateAligned(NULL, n);
|
||||
}
|
||||
|
||||
void Init();
|
||||
|
||||
// Free all blocks and return the total space used which is the sums of sizes
|
||||
// of the all the allocated blocks.
|
||||
uint64 FreeBlocks();
|
||||
|
||||
// Add object pointer and cleanup function pointer to the list.
|
||||
// TODO(rohananil, cfallin): We could pass in a sub-arena into this method
|
||||
// to avoid polluting blocks of this arena with list nodes. This would help in
|
||||
// mixed mode (where many protobufs have cc_enable_arenas=false), and is an
|
||||
// alternative to a chunked linked-list, but with extra overhead of *next.
|
||||
void AddListNode(void* elem, void (*cleanup)(void*));
|
||||
// Delete or Destruct all objects owned by the arena.
|
||||
void CleanupList();
|
||||
uint64 ResetInternal();
|
||||
|
||||
inline void SetThreadCacheBlock(Block* block) {
|
||||
thread_cache().last_block_used_ = block;
|
||||
thread_cache().last_lifecycle_id_seen = lifecycle_id_;
|
||||
}
|
||||
|
||||
int64 lifecycle_id_; // Unique for each arena. Changes on Reset().
|
||||
|
||||
google::protobuf::internal::AtomicWord blocks_; // Head of linked list of all allocated blocks
|
||||
google::protobuf::internal::AtomicWord hint_; // Fast thread-local block access
|
||||
uint64 space_allocated_; // Sum of sizes of all allocated blocks.
|
||||
|
||||
// Node contains the ptr of the object to be cleaned up and the associated
|
||||
// cleanup function ptr.
|
||||
struct Node {
|
||||
void* elem; // Pointer to the object to be cleaned up.
|
||||
void (*cleanup)(void*); // Function pointer to the destructor or deleter.
|
||||
Node* next; // Next node in the list.
|
||||
};
|
||||
|
||||
google::protobuf::internal::AtomicWord cleanup_list_; // Head of a linked list of nodes containing object
|
||||
// ptrs and cleanup methods.
|
||||
|
||||
bool owns_first_block_; // Indicates that arena owns the first block
|
||||
mutable Mutex blocks_lock_;
|
||||
|
||||
void AddBlock(Block* b);
|
||||
// Access must be synchronized, either by blocks_lock_ or by being called from
|
||||
// Init()/Reset().
|
||||
void AddBlockInternal(Block* b);
|
||||
void* SlowAlloc(size_t n);
|
||||
Block* FindBlock(void* me);
|
||||
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);
|
||||
};
|
||||
|
||||
// Defined above for supporting environments without RTTI.
|
||||
#undef RTTI_TYPE_ID
|
||||
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_ARENA_H__
|
||||
@@ -0,0 +1,50 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#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
|
||||
@@ -0,0 +1,91 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
template <typename T, bool use_arena>
|
||||
void TestParseCorruptedString(const T& message) {
|
||||
int success_count = 0;
|
||||
string s = message.SerializeAsString();
|
||||
const int kMaxIters = 900;
|
||||
const int stride = s.size() <= kMaxIters ? 1 : s.size() / kMaxIters;
|
||||
const int start = stride == 1 || use_arena ? 0 : (stride + 1) / 2;
|
||||
for (int i = start; i < s.size(); i += stride) {
|
||||
for (int c = 1 + (i % 17); c < 256; c += 2 * c + (i & 3)) {
|
||||
s[i] ^= c;
|
||||
google::protobuf::Arena arena;
|
||||
T* message =
|
||||
google::protobuf::Arena::CreateMessage<T>(use_arena ? &arena : NULL);
|
||||
if (message->ParseFromString(s)) {
|
||||
++success_count;
|
||||
}
|
||||
if (!use_arena) {
|
||||
delete message;
|
||||
}
|
||||
s[i] ^= c; // Restore s to its original state.
|
||||
}
|
||||
}
|
||||
// This next line is a low bar. But getting through the test without crashing
|
||||
// due to use-after-free or other bugs is a big part of what we're checking.
|
||||
GOOGLE_CHECK_GT(success_count, 0);
|
||||
}
|
||||
|
||||
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__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,53 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// The ArenaString implementation is not included in the open-source release. Do
|
||||
// not include this file in the distribution.
|
||||
|
||||
#include <google/protobuf/arenastring.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
|
||||
void ArenaStringPtr::AssignWithDefault(const ::std::string* default_value,
|
||||
ArenaStringPtr value) {
|
||||
const ::std::string* me = *UnsafeRawStringPointer();
|
||||
const ::std::string* other = *value.UnsafeRawStringPointer();
|
||||
// If the pointers are the same then do nothing.
|
||||
if (me != other) {
|
||||
SetNoArena(default_value, value.GetNoArena());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -0,0 +1,314 @@
|
||||
// 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_ARENASTRING_H__
|
||||
#define GOOGLE_PROTOBUF_ARENASTRING_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/fastmem.h>
|
||||
#include <google/protobuf/arena.h>
|
||||
|
||||
|
||||
|
||||
// This is the implementation of arena string fields written for the open-source
|
||||
// release. The ArenaStringPtr struct below is an internal implementation class
|
||||
// and *should not be used* by user code. It is used to collect string
|
||||
// operations together into one place and abstract away the underlying
|
||||
// string-field pointer representation, so that (for example) an alternate
|
||||
// implementation that knew more about ::std::string's internals could integrate more
|
||||
// closely with the arena allocator.
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
struct LIBPROTOBUF_EXPORT ArenaStringPtr {
|
||||
inline void Set(const ::std::string* default_value,
|
||||
const ::std::string& value, ::google::protobuf::Arena* arena) {
|
||||
if (ptr_ == default_value) {
|
||||
CreateInstance(arena, &value);
|
||||
} else {
|
||||
*ptr_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Basic accessors.
|
||||
inline const ::std::string& Get() const { return *ptr_; }
|
||||
|
||||
inline ::std::string* Mutable(const ::std::string* default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
if (ptr_ == default_value) {
|
||||
CreateInstance(arena, default_value);
|
||||
}
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
// Release returns a ::std::string* instance that is heap-allocated and is not
|
||||
// Own()'d by any arena. If the field was not set, it returns NULL. The caller
|
||||
// retains ownership. Clears this field back to NULL state. Used to implement
|
||||
// release_<field>() methods on generated classes.
|
||||
inline ::std::string* Release(const ::std::string* default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
if (ptr_ == default_value) {
|
||||
return NULL;
|
||||
}
|
||||
::std::string* released = NULL;
|
||||
if (arena != NULL) {
|
||||
// ptr_ is owned by the arena -- we need to return a copy.
|
||||
released = new ::std::string(*ptr_);
|
||||
} else {
|
||||
released = ptr_;
|
||||
}
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
return released;
|
||||
}
|
||||
|
||||
// UnsafeArenaRelease returns a ::std::string*, but it may be arena-owned (i.e.
|
||||
// have its destructor already registered) if arena != NULL. If the field was
|
||||
// not set, this returns NULL. This method clears this field back to NULL
|
||||
// state. Used to implement unsafe_arena_release_<field>() methods on
|
||||
// generated classes.
|
||||
inline ::std::string* UnsafeArenaRelease(const ::std::string* default_value,
|
||||
::google::protobuf::Arena* /* arena */) {
|
||||
if (ptr_ == default_value) {
|
||||
return NULL;
|
||||
}
|
||||
::std::string* released = ptr_;
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
return released;
|
||||
}
|
||||
|
||||
// Takes a string that is heap-allocated, and takes ownership. The string's
|
||||
// destructor is registered with the arena. Used to implement
|
||||
// set_allocated_<field> in generated classes.
|
||||
inline void SetAllocated(const ::std::string* default_value,
|
||||
::std::string* value, ::google::protobuf::Arena* arena) {
|
||||
if (arena == NULL && ptr_ != default_value) {
|
||||
Destroy(default_value, arena);
|
||||
}
|
||||
if (value != NULL) {
|
||||
ptr_ = value;
|
||||
if (arena != NULL) {
|
||||
arena->Own(value);
|
||||
}
|
||||
} else {
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
}
|
||||
}
|
||||
|
||||
// Takes a string that has lifetime equal to the arena's lifetime. The arena
|
||||
// must be non-null. It is safe only to pass this method a value returned by
|
||||
// UnsafeArenaRelease() on another field of a message in the same arena. Used
|
||||
// to implement unsafe_arena_set_allocated_<field> in generated classes.
|
||||
inline void UnsafeArenaSetAllocated(const ::std::string* default_value,
|
||||
::std::string* value,
|
||||
::google::protobuf::Arena* /* arena */) {
|
||||
if (value != NULL) {
|
||||
ptr_ = value;
|
||||
} else {
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
}
|
||||
}
|
||||
|
||||
// Swaps internal pointers. Arena-safety semantics: this is guarded by the
|
||||
// logic in Swap()/UnsafeArenaSwap() at the message level, so this method is
|
||||
// 'unsafe' if called directly.
|
||||
GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(ArenaStringPtr* other) {
|
||||
std::swap(ptr_, other->ptr_);
|
||||
}
|
||||
|
||||
// Frees storage (if not on an arena).
|
||||
inline void Destroy(const ::std::string* default_value,
|
||||
::google::protobuf::Arena* arena) {
|
||||
if (arena == NULL && ptr_ != default_value) {
|
||||
delete ptr_;
|
||||
}
|
||||
}
|
||||
|
||||
// Clears content, but keeps allocated string if arena != NULL, to avoid the
|
||||
// overhead of heap operations. After this returns, the content (as seen by
|
||||
// the user) will always be the empty string. Assumes that |default_value|
|
||||
// is an empty string.
|
||||
inline void ClearToEmpty(const ::std::string* default_value,
|
||||
::google::protobuf::Arena* /* arena */) {
|
||||
if (ptr_ == default_value) {
|
||||
// Already set to default (which is empty) -- do nothing.
|
||||
} else {
|
||||
ptr_->clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Clears content, but keeps allocated string if arena != NULL, to avoid the
|
||||
// overhead of heap operations. After this returns, the content (as seen by
|
||||
// the user) will always be equal to |default_value|.
|
||||
inline void ClearToDefault(const ::std::string* default_value,
|
||||
::google::protobuf::Arena* /* arena */) {
|
||||
if (ptr_ == default_value) {
|
||||
// Already set to default -- do nothing.
|
||||
} else {
|
||||
// Have another allocated string -- rather than throwing this away and
|
||||
// resetting ptr_ to the canonical default string instance, we just reuse
|
||||
// this instance.
|
||||
*ptr_ = *default_value;
|
||||
}
|
||||
}
|
||||
|
||||
// Called from generated code / reflection runtime only. Resets value to point
|
||||
// to a default string pointer, with the semantics that this ArenaStringPtr
|
||||
// does not own the pointed-to memory. Disregards initial value of ptr_ (so
|
||||
// this is the *ONLY* safe method to call after construction or when
|
||||
// reinitializing after becoming the active field in a oneof union).
|
||||
inline void UnsafeSetDefault(const ::std::string* default_value) {
|
||||
// Casting away 'const' is safe here: accessors ensure that ptr_ is only
|
||||
// returned as a const if it is equal to default_value.
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
}
|
||||
|
||||
// The 'NoArena' variants of methods below assume arena == NULL and are
|
||||
// optimized to provide very little overhead relative to a raw string pointer
|
||||
// (while still being in-memory compatible with other code that assumes
|
||||
// ArenaStringPtr). Note the invariant that a class instance that has only
|
||||
// ever been mutated by NoArena methods must *only* be in the String state
|
||||
// (i.e., tag bits are not used), *NEVER* ArenaString. This allows all
|
||||
// tagged-pointer manipulations to be avoided.
|
||||
inline void SetNoArena(const ::std::string* default_value,
|
||||
const ::std::string& value) {
|
||||
if (ptr_ == default_value) {
|
||||
CreateInstanceNoArena(&value);
|
||||
} else {
|
||||
*ptr_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
#if LANG_CXX11
|
||||
void SetNoArena(const ::std::string* default_value, ::std::string&& value) {
|
||||
if (IsDefault(default_value)) {
|
||||
ptr_ = new ::std::string(std::move(value));
|
||||
} else {
|
||||
*ptr_ = std::move(value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void AssignWithDefault(const ::std::string* default_value, ArenaStringPtr value);
|
||||
|
||||
inline const ::std::string& GetNoArena() const { return *ptr_; }
|
||||
|
||||
inline ::std::string* MutableNoArena(const ::std::string* default_value) {
|
||||
if (ptr_ == default_value) {
|
||||
CreateInstanceNoArena(default_value);
|
||||
}
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
inline ::std::string* ReleaseNoArena(const ::std::string* default_value) {
|
||||
if (ptr_ == default_value) {
|
||||
return NULL;
|
||||
} else {
|
||||
::std::string* released = ptr_;
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
return released;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetAllocatedNoArena(const ::std::string* default_value,
|
||||
::std::string* value) {
|
||||
if (ptr_ != default_value) {
|
||||
delete ptr_;
|
||||
}
|
||||
if (value != NULL) {
|
||||
ptr_ = value;
|
||||
} else {
|
||||
ptr_ = const_cast< ::std::string* >(default_value);
|
||||
}
|
||||
}
|
||||
|
||||
inline void DestroyNoArena(const ::std::string* default_value) {
|
||||
if (ptr_ != default_value) {
|
||||
delete ptr_;
|
||||
}
|
||||
}
|
||||
|
||||
inline void ClearToEmptyNoArena(const ::std::string* default_value) {
|
||||
if (ptr_ == default_value) {
|
||||
// Nothing: already equal to default (which is the empty string).
|
||||
} else {
|
||||
ptr_->clear();
|
||||
}
|
||||
}
|
||||
|
||||
inline void ClearToDefaultNoArena(const ::std::string* default_value) {
|
||||
if (ptr_ == default_value) {
|
||||
// Nothing: already set to default.
|
||||
} else {
|
||||
// Reuse existing allocated instance.
|
||||
*ptr_ = *default_value;
|
||||
}
|
||||
}
|
||||
|
||||
// Internal accessor used only at parse time to provide direct access to the
|
||||
// raw pointer from the shared parse routine (in the non-arenas case). The
|
||||
// parse routine does the string allocation in order to save code size in the
|
||||
// generated parsing code.
|
||||
inline ::std::string** UnsafeRawStringPointer() {
|
||||
return &ptr_;
|
||||
}
|
||||
|
||||
inline bool IsDefault(const ::std::string* default_value) const {
|
||||
return ptr_ == default_value;
|
||||
}
|
||||
|
||||
private:
|
||||
::std::string* ptr_;
|
||||
|
||||
GOOGLE_ATTRIBUTE_NOINLINE void CreateInstance(::google::protobuf::Arena* arena,
|
||||
const ::std::string* initial_value) {
|
||||
GOOGLE_DCHECK(initial_value != NULL);
|
||||
ptr_ = new ::std::string(*initial_value);
|
||||
if (arena != NULL) {
|
||||
arena->Own(ptr_);
|
||||
}
|
||||
}
|
||||
GOOGLE_ATTRIBUTE_NOINLINE void CreateInstanceNoArena(const ::std::string* initial_value) {
|
||||
GOOGLE_DCHECK(initial_value != NULL);
|
||||
ptr_ = new ::std::string(*initial_value);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_ARENASTRING_H__
|
||||
@@ -0,0 +1,108 @@
|
||||
// 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.
|
||||
|
||||
// Based on mvels@'s frankenstring.
|
||||
|
||||
#include <google/protobuf/arenastring.h>
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#ifndef _SHARED_PTR_H
|
||||
#include <google/protobuf/stubs/shared_ptr.h>
|
||||
#endif
|
||||
#include <cstdlib>
|
||||
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace google {
|
||||
using google::protobuf::internal::ArenaString;
|
||||
using google::protobuf::internal::ArenaStringPtr;
|
||||
|
||||
namespace protobuf {
|
||||
|
||||
|
||||
static string WrapString(const char* value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// Test ArenaStringPtr with arena == NULL.
|
||||
TEST(ArenaStringPtrTest, ArenaStringPtrOnHeap) {
|
||||
ArenaStringPtr field;
|
||||
::std::string default_value = "default";
|
||||
field.UnsafeSetDefault(&default_value);
|
||||
EXPECT_EQ(string("default"), field.Get());
|
||||
field.Set(&default_value, WrapString("Test short"), NULL);
|
||||
EXPECT_EQ(string("Test short"), field.Get());
|
||||
field.Set(&default_value, WrapString("Test long long long long value"), NULL);
|
||||
EXPECT_EQ(string("Test long long long long value"), field.Get());
|
||||
field.Set(&default_value, string(""), NULL);
|
||||
field.Destroy(&default_value, NULL);
|
||||
|
||||
ArenaStringPtr field2;
|
||||
field2.UnsafeSetDefault(&default_value);
|
||||
::std::string* mut = field2.Mutable(&default_value, NULL);
|
||||
EXPECT_EQ(mut, field2.Mutable(&default_value, NULL));
|
||||
EXPECT_EQ(mut, &field2.Get());
|
||||
EXPECT_NE(&default_value, mut);
|
||||
EXPECT_EQ(string("default"), *mut);
|
||||
*mut = "Test long long long long value"; // ensure string allocates storage
|
||||
EXPECT_EQ(string("Test long long long long value"), field2.Get());
|
||||
field2.Destroy(&default_value, NULL);
|
||||
}
|
||||
|
||||
TEST(ArenaStringPtrTest, ArenaStringPtrOnArena) {
|
||||
google::protobuf::Arena arena;
|
||||
ArenaStringPtr field;
|
||||
::std::string default_value = "default";
|
||||
field.UnsafeSetDefault(&default_value);
|
||||
EXPECT_EQ(string("default"), field.Get());
|
||||
field.Set(&default_value, WrapString("Test short"), &arena);
|
||||
EXPECT_EQ(string("Test short"), field.Get());
|
||||
field.Set(&default_value, WrapString("Test long long long long value"), &arena);
|
||||
EXPECT_EQ(string("Test long long long long value"), field.Get());
|
||||
field.Set(&default_value, string(""), &arena);
|
||||
field.Destroy(&default_value, &arena);
|
||||
|
||||
ArenaStringPtr field2;
|
||||
field2.UnsafeSetDefault(&default_value);
|
||||
::std::string* mut = field2.Mutable(&default_value, &arena);
|
||||
EXPECT_EQ(mut, field2.Mutable(&default_value, &arena));
|
||||
EXPECT_EQ(mut, &field2.Get());
|
||||
EXPECT_NE(&default_value, mut);
|
||||
EXPECT_EQ(string("default"), *mut);
|
||||
*mut = "Test long long long long value"; // ensure string allocates storage
|
||||
EXPECT_EQ(string("Test long long long long value"), field2.Get());
|
||||
field2.Destroy(&default_value, &arena);
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
+47
-6
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -34,7 +34,10 @@
|
||||
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
|
||||
#include <google/protobuf/compiler/plugin.pb.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
@@ -42,8 +45,40 @@ namespace protobuf {
|
||||
namespace compiler {
|
||||
|
||||
CodeGenerator::~CodeGenerator() {}
|
||||
|
||||
bool CodeGenerator::GenerateAll(
|
||||
const std::vector<const FileDescriptor*>& files,
|
||||
const string& parameter,
|
||||
GeneratorContext* generator_context,
|
||||
string* error) const {
|
||||
// Default implemenation is just to call the per file method, and prefix any
|
||||
// error string with the file to provide context.
|
||||
bool succeeded = true;
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
const FileDescriptor* file = files[i];
|
||||
succeeded = Generate(file, parameter, generator_context, error);
|
||||
if (!succeeded && error && error->empty()) {
|
||||
*error = "Code generator returned false but provided no error "
|
||||
"description.";
|
||||
}
|
||||
if (error && !error->empty()) {
|
||||
*error = file->name() + ": " + *error;
|
||||
break;
|
||||
}
|
||||
if (!succeeded) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
GeneratorContext::~GeneratorContext() {}
|
||||
|
||||
io::ZeroCopyOutputStream*
|
||||
GeneratorContext::OpenForAppend(const string& filename) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert(
|
||||
const string& filename, const string& insertion_point) {
|
||||
GOOGLE_LOG(FATAL) << "This GeneratorContext does not support insertion.";
|
||||
@@ -51,19 +86,25 @@ io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert(
|
||||
}
|
||||
|
||||
void GeneratorContext::ListParsedFiles(
|
||||
vector<const FileDescriptor*>* output) {
|
||||
std::vector<const FileDescriptor*>* output) {
|
||||
GOOGLE_LOG(FATAL) << "This GeneratorContext does not support ListParsedFiles";
|
||||
}
|
||||
|
||||
void GeneratorContext::GetCompilerVersion(Version* version) const {
|
||||
version->set_major(GOOGLE_PROTOBUF_VERSION / 1000000);
|
||||
version->set_minor(GOOGLE_PROTOBUF_VERSION / 1000 % 1000);
|
||||
version->set_patch(GOOGLE_PROTOBUF_VERSION % 1000);
|
||||
version->set_suffix(GOOGLE_PROTOBUF_VERSION_SUFFIX);
|
||||
}
|
||||
|
||||
// Parses a set of comma-delimited name/value pairs.
|
||||
void ParseGeneratorParameter(const string& text,
|
||||
vector<pair<string, string> >* output) {
|
||||
vector<string> parts;
|
||||
SplitStringUsing(text, ",", &parts);
|
||||
std::vector<std::pair<string, string> >* output) {
|
||||
std::vector<string> parts = Split(text, ",", true);
|
||||
|
||||
for (int i = 0; i < parts.size(); i++) {
|
||||
string::size_type equals_pos = parts[i].find_first_of('=');
|
||||
pair<string, string> value;
|
||||
std::pair<string, string> value;
|
||||
if (equals_pos == string::npos) {
|
||||
value.first = parts[i];
|
||||
value.second = "";
|
||||
+39
-9
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -50,6 +50,7 @@ namespace io { class ZeroCopyOutputStream; }
|
||||
class FileDescriptor;
|
||||
|
||||
namespace compiler {
|
||||
class Version;
|
||||
|
||||
// Defined in this file.
|
||||
class CodeGenerator;
|
||||
@@ -66,11 +67,11 @@ class LIBPROTOC_EXPORT CodeGenerator {
|
||||
// Generates code for the given proto file, generating one or more files in
|
||||
// the given output directory.
|
||||
//
|
||||
// A parameter to be passed to the generator can be specified on the
|
||||
// command line. This is intended to be used by Java and similar languages
|
||||
// to specify which specific class from the proto file is to be generated,
|
||||
// though it could have other uses as well. It is empty if no parameter was
|
||||
// given.
|
||||
// A parameter to be passed to the generator can be specified on the command
|
||||
// line. This is intended to be used to pass generator specific parameters.
|
||||
// It is empty if no parameter was given. ParseGeneratorParameter (below),
|
||||
// can be used to accept multiple parameters within the single parameter
|
||||
// command line flag.
|
||||
//
|
||||
// Returns true if successful. Otherwise, sets *error to a description of
|
||||
// the problem (e.g. "invalid parameter") and returns false.
|
||||
@@ -79,6 +80,28 @@ class LIBPROTOC_EXPORT CodeGenerator {
|
||||
GeneratorContext* generator_context,
|
||||
string* error) const = 0;
|
||||
|
||||
// Generates code for all given proto files.
|
||||
//
|
||||
// WARNING: The canonical code generator design produces one or two output
|
||||
// files per input .proto file, and we do not wish to encourage alternate
|
||||
// designs.
|
||||
//
|
||||
// A parameter is given as passed on the command line, as in |Generate()|
|
||||
// above.
|
||||
//
|
||||
// Returns true if successful. Otherwise, sets *error to a description of
|
||||
// the problem (e.g. "invalid parameter") and returns false.
|
||||
virtual bool GenerateAll(const std::vector<const FileDescriptor*>& files,
|
||||
const string& parameter,
|
||||
GeneratorContext* generator_context,
|
||||
string* error) const;
|
||||
|
||||
// This is no longer used, but this class is part of the opensource protobuf
|
||||
// library, so it has to remain to keep vtables the same for the current
|
||||
// version of the library. When protobufs does a api breaking change, the
|
||||
// method can be removed.
|
||||
virtual bool HasGenerateAll() const { return true; }
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodeGenerator);
|
||||
};
|
||||
@@ -104,6 +127,9 @@ class LIBPROTOC_EXPORT GeneratorContext {
|
||||
// contain "." or ".." components.
|
||||
virtual io::ZeroCopyOutputStream* Open(const string& filename) = 0;
|
||||
|
||||
// Similar to Open() but the output will be appended to the file if exists
|
||||
virtual io::ZeroCopyOutputStream* OpenForAppend(const string& filename);
|
||||
|
||||
// Creates a ZeroCopyOutputStream which will insert code into the given file
|
||||
// at the given insertion point. See plugin.proto (plugin.pb.h) for more
|
||||
// information on insertion points. The default implementation
|
||||
@@ -116,7 +142,11 @@ class LIBPROTOC_EXPORT GeneratorContext {
|
||||
// Returns a vector of FileDescriptors for all the files being compiled
|
||||
// in this run. Useful for languages, such as Go, that treat files
|
||||
// differently when compiled as a set rather than individually.
|
||||
virtual void ListParsedFiles(vector<const FileDescriptor*>* output);
|
||||
virtual void ListParsedFiles(std::vector<const FileDescriptor*>* output);
|
||||
|
||||
// Retrieves the version number of the protocol compiler associated with
|
||||
// this GeneratorContext.
|
||||
virtual void GetCompilerVersion(Version* version) const;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorContext);
|
||||
@@ -132,8 +162,8 @@ typedef GeneratorContext OutputDirectory;
|
||||
// "foo=bar,baz,qux=corge"
|
||||
// parses to the pairs:
|
||||
// ("foo", "bar"), ("baz", ""), ("qux", "corge")
|
||||
extern void ParseGeneratorParameter(const string&,
|
||||
vector<pair<string, string> >*);
|
||||
extern void LIBPROTOC_EXPORT ParseGeneratorParameter(const string&,
|
||||
std::vector<std::pair<string, string> >*);
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
+691
-162
File diff suppressed because it is too large
Load Diff
+89
-26
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -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>
|
||||
@@ -48,11 +49,15 @@
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class FileDescriptor; // descriptor.h
|
||||
class Descriptor; // descriptor.h
|
||||
class DescriptorPool; // descriptor.h
|
||||
class FileDescriptor; // descriptor.h
|
||||
class FileDescriptorProto; // descriptor.pb.h
|
||||
template<typename T> class RepeatedPtrField; // repeated_field.h
|
||||
|
||||
} // namespace protobuf
|
||||
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
|
||||
class CodeGenerator; // code_generator.h
|
||||
@@ -139,14 +144,14 @@ class LIBPROTOC_EXPORT CommandLineInterface {
|
||||
// plugin [--out=OUTDIR] [--parameter=PARAMETER] PROTO_FILES < DESCRIPTORS
|
||||
// --out indicates the output directory (as passed to the --foo_out
|
||||
// parameter); if omitted, the current directory should be used. --parameter
|
||||
// gives the generator parameter, if any was provided. The PROTO_FILES list
|
||||
// the .proto files which were given on the compiler command-line; these are
|
||||
// the files for which the plugin is expected to generate output code.
|
||||
// Finally, DESCRIPTORS is an encoded FileDescriptorSet (as defined in
|
||||
// descriptor.proto). This is piped to the plugin's stdin. The set will
|
||||
// include descriptors for all the files listed in PROTO_FILES as well as
|
||||
// all files that they import. The plugin MUST NOT attempt to read the
|
||||
// PROTO_FILES directly -- it must use the FileDescriptorSet.
|
||||
// gives the generator parameter, if any was provided (see below). The
|
||||
// PROTO_FILES list the .proto files which were given on the compiler
|
||||
// command-line; these are the files for which the plugin is expected to
|
||||
// generate output code. Finally, DESCRIPTORS is an encoded FileDescriptorSet
|
||||
// (as defined in descriptor.proto). This is piped to the plugin's stdin.
|
||||
// The set will include descriptors for all the files listed in PROTO_FILES as
|
||||
// well as all files that they import. The plugin MUST NOT attempt to read
|
||||
// the PROTO_FILES directly -- it must use the FileDescriptorSet.
|
||||
//
|
||||
// The plugin should generate whatever files are necessary, as code generators
|
||||
// normally do. It should write the names of all files it generates to
|
||||
@@ -154,6 +159,13 @@ class LIBPROTOC_EXPORT CommandLineInterface {
|
||||
// names or relative to the current directory. If any errors occur, error
|
||||
// messages should be written to stderr. If an error is fatal, the plugin
|
||||
// should exit with a non-zero exit code.
|
||||
//
|
||||
// Plugins can have generator parameters similar to normal built-in
|
||||
// generators. Extra generator parameters can be passed in via a matching
|
||||
// "_opt" parameter. For example:
|
||||
// protoc --plug_out=enable_bar:outdir --plug_opt=enable_baz
|
||||
// This will pass "enable_bar,enable_baz" as the parameter to the plugin.
|
||||
//
|
||||
void AllowPlugins(const string& exe_name_prefix);
|
||||
|
||||
// Run the Protocol Compiler with the given command-line parameters.
|
||||
@@ -189,6 +201,7 @@ class LIBPROTOC_EXPORT CommandLineInterface {
|
||||
class ErrorPrinter;
|
||||
class GeneratorContextImpl;
|
||||
class MemoryOutputStream;
|
||||
typedef hash_map<string, GeneratorContextImpl*> GeneratorContextMap;
|
||||
|
||||
// Clear state from previous Run().
|
||||
void Clear();
|
||||
@@ -209,11 +222,12 @@ class LIBPROTOC_EXPORT CommandLineInterface {
|
||||
// Parse all command-line arguments.
|
||||
ParseArgumentStatus ParseArguments(int argc, const char* const argv[]);
|
||||
|
||||
|
||||
// Parses a command-line argument into a name/value pair. Returns
|
||||
// true if the next argument in the argv should be used as the value,
|
||||
// false otherwise.
|
||||
//
|
||||
// Exmaples:
|
||||
// Examples:
|
||||
// "-Isrc/protos" ->
|
||||
// name = "-I", value = "src/protos"
|
||||
// "--cpp_out=src/foo.pb2.cc" ->
|
||||
@@ -231,20 +245,26 @@ class LIBPROTOC_EXPORT CommandLineInterface {
|
||||
|
||||
// Generate the given output file from the given input.
|
||||
struct OutputDirective; // see below
|
||||
bool GenerateOutput(const vector<const FileDescriptor*>& parsed_files,
|
||||
bool GenerateOutput(const std::vector<const FileDescriptor*>& parsed_files,
|
||||
const OutputDirective& output_directive,
|
||||
GeneratorContext* generator_context);
|
||||
bool GeneratePluginOutput(const vector<const FileDescriptor*>& parsed_files,
|
||||
const string& plugin_name,
|
||||
const string& parameter,
|
||||
GeneratorContext* generator_context,
|
||||
string* error);
|
||||
bool GeneratePluginOutput(
|
||||
const std::vector<const FileDescriptor*>& parsed_files,
|
||||
const string& plugin_name, const string& parameter,
|
||||
GeneratorContext* generator_context, string* error);
|
||||
|
||||
// Implements --encode and --decode.
|
||||
bool EncodeOrDecode(const DescriptorPool* pool);
|
||||
|
||||
// Implements the --descriptor_set_out option.
|
||||
bool WriteDescriptorSet(const vector<const FileDescriptor*> parsed_files);
|
||||
bool WriteDescriptorSet(
|
||||
const std::vector<const FileDescriptor*> parsed_files);
|
||||
|
||||
// Implements the --dependency_out option
|
||||
bool GenerateDependencyManifestFile(
|
||||
const std::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
|
||||
@@ -253,12 +273,31 @@ class LIBPROTOC_EXPORT CommandLineInterface {
|
||||
// in order. Any files in *already_seen will not be added, and each file
|
||||
// added will be inserted into *already_seen. If include_source_code_info is
|
||||
// true then include the source code information in the FileDescriptorProtos.
|
||||
// If include_json_name is true, populate the json_name field of
|
||||
// FieldDescriptorProto for all fields.
|
||||
static void GetTransitiveDependencies(
|
||||
const FileDescriptor* file,
|
||||
bool include_json_name,
|
||||
bool include_source_code_info,
|
||||
set<const FileDescriptor*>* already_seen,
|
||||
std::set<const FileDescriptor*>* already_seen,
|
||||
RepeatedPtrField<FileDescriptorProto>* output);
|
||||
|
||||
// Implements the --print_free_field_numbers. This function prints free field
|
||||
// numbers into stdout for the message and it's nested message types in
|
||||
// post-order, i.e. nested types first. Printed range are left-right
|
||||
// inclusive, i.e. [a, b].
|
||||
//
|
||||
// Groups:
|
||||
// For historical reasons, groups are considered to share the same
|
||||
// field number space with the parent message, thus it will not print free
|
||||
// field numbers for groups. The field numbers used in the groups are
|
||||
// excluded in the free field numbers of the parent message.
|
||||
//
|
||||
// Extension Ranges:
|
||||
// Extension ranges are considered ocuppied field numbers and they will not be
|
||||
// listed as free numbers in the output.
|
||||
void PrintFreeFieldNumbers(const Descriptor* descriptor);
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
// The name of the executable as invoked (i.e. argv[0]).
|
||||
@@ -274,14 +313,16 @@ class LIBPROTOC_EXPORT CommandLineInterface {
|
||||
CodeGenerator* generator;
|
||||
string help_text;
|
||||
};
|
||||
typedef map<string, GeneratorInfo> GeneratorMap;
|
||||
typedef std::map<string, GeneratorInfo> GeneratorMap;
|
||||
GeneratorMap generators_by_flag_name_;
|
||||
GeneratorMap generators_by_option_name_;
|
||||
// A map from generator names to the parameters specified using the option
|
||||
// flag. For example, if the user invokes the compiler with:
|
||||
// protoc --foo_out=outputdir --foo_opt=enable_bar ...
|
||||
// Then there will be an entry ("--foo_out", "enable_bar") in this map.
|
||||
map<string, string> generator_parameters_;
|
||||
std::map<string, string> generator_parameters_;
|
||||
// Similar to generator_parameters_, but stores the parameters for plugins.
|
||||
std::map<string, string> plugin_parameters_;
|
||||
|
||||
// See AllowPlugins(). If this is empty, plugins aren't allowed.
|
||||
string plugin_prefix_;
|
||||
@@ -289,17 +330,25 @@ class LIBPROTOC_EXPORT CommandLineInterface {
|
||||
// Maps specific plugin names to files. When executing a plugin, this map
|
||||
// is searched first to find the plugin executable. If not found here, the
|
||||
// PATH (or other OS-specific search strategy) is searched.
|
||||
map<string, string> plugins_;
|
||||
std::map<string, string> plugins_;
|
||||
|
||||
// Stuff parsed from command line.
|
||||
enum Mode {
|
||||
MODE_COMPILE, // Normal mode: parse .proto files and compile them.
|
||||
MODE_ENCODE, // --encode: read text from stdin, write binary to stdout.
|
||||
MODE_DECODE // --decode: read binary from stdin, write text to stdout.
|
||||
MODE_DECODE, // --decode: read binary from stdin, write text to stdout.
|
||||
MODE_PRINT, // Print mode: print info of the given .proto files and exit.
|
||||
};
|
||||
|
||||
Mode mode_;
|
||||
|
||||
enum PrintMode {
|
||||
PRINT_NONE, // Not in MODE_PRINT
|
||||
PRINT_FREE_FIELDS, // --print_free_fields
|
||||
};
|
||||
|
||||
PrintMode print_mode_;
|
||||
|
||||
enum ErrorFormat {
|
||||
ERROR_FORMAT_GCC, // GCC error output format (default).
|
||||
ERROR_FORMAT_MSVS // Visual Studio output (--error_format=msvs).
|
||||
@@ -307,8 +356,18 @@ class LIBPROTOC_EXPORT CommandLineInterface {
|
||||
|
||||
ErrorFormat error_format_;
|
||||
|
||||
vector<pair<string, string> > proto_path_; // Search path for proto files.
|
||||
vector<string> input_files_; // Names of the input proto files.
|
||||
std::vector<std::pair<string, string> >
|
||||
proto_path_; // Search path for proto files.
|
||||
std::vector<string> input_files_; // Names of the input proto files.
|
||||
|
||||
// Names of proto files which are allowed to be imported. Used by build
|
||||
// systems to enforce depend-on-what-you-import.
|
||||
std::set<string> direct_dependencies_;
|
||||
bool direct_dependencies_explicitly_set_;
|
||||
|
||||
// If there's a violation of depend-on-what-you-import, this string will be
|
||||
// presented to the user. "%s" will be replaced with the violating import.
|
||||
string direct_dependencies_violation_msg_;
|
||||
|
||||
// output_directives_ lists all the files we are supposed to output and what
|
||||
// generator to use for each.
|
||||
@@ -318,7 +377,7 @@ class LIBPROTOC_EXPORT CommandLineInterface {
|
||||
string parameter;
|
||||
string output_location;
|
||||
};
|
||||
vector<OutputDirective> output_directives_;
|
||||
std::vector<OutputDirective> output_directives_;
|
||||
|
||||
// When using --encode or --decode, this names the type we are encoding or
|
||||
// decoding. (Empty string indicates --decode_raw.)
|
||||
@@ -328,6 +387,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.
|
||||
+503
-32
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -40,6 +40,10 @@
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <memory>
|
||||
#ifndef _SHARED_PTR_H
|
||||
#include <google/protobuf/stubs/shared_ptr.h>
|
||||
#endif
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
@@ -47,21 +51,29 @@
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/compiler/command_line_interface.h>
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/compiler/mock_code_generator.h>
|
||||
#include <google/protobuf/compiler/subprocess.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/unittest.pb.h>
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/stubs/stringprintf.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/stubs/substitute.h>
|
||||
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/testing/googletest.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
|
||||
// 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
|
||||
|
||||
#if defined(_WIN32)
|
||||
#ifndef STDIN_FILENO
|
||||
#define STDIN_FILENO 0
|
||||
@@ -76,6 +88,10 @@ namespace compiler {
|
||||
|
||||
namespace {
|
||||
|
||||
bool FileExists(const string& path) {
|
||||
return File::Exists(path);
|
||||
}
|
||||
|
||||
class CommandLineInterfaceTest : public testing::Test {
|
||||
protected:
|
||||
virtual void SetUp();
|
||||
@@ -85,6 +101,7 @@ class CommandLineInterfaceTest : public testing::Test {
|
||||
// command is automatically split on spaces, and the string "$tmpdir"
|
||||
// is replaced with TestTempDir().
|
||||
void Run(const string& command);
|
||||
void RunWithArgs(vector<string> args);
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Methods to set up the test (called before Run()).
|
||||
@@ -102,6 +119,16 @@ class CommandLineInterfaceTest : public testing::Test {
|
||||
// Create a subdirectory within temp_directory_.
|
||||
void CreateTempDir(const string& name);
|
||||
|
||||
#ifdef PROTOBUF_OPENSOURCE
|
||||
// Change working directory to temp directory.
|
||||
void SwitchToTempDirectory() {
|
||||
File::ChangeWorkingDirectory(temp_directory_);
|
||||
}
|
||||
#else // !PROTOBUF_OPENSOURCE
|
||||
// TODO(teboring): Figure out how to change and get working directory in
|
||||
// google3.
|
||||
#endif // !PROTOBUF_OPENSOURCE
|
||||
|
||||
void SetInputsAreProtoPathRelative(bool enable) {
|
||||
cli_.SetInputsAreProtoPathRelative(enable);
|
||||
}
|
||||
@@ -126,6 +153,9 @@ class CommandLineInterfaceTest : public testing::Test {
|
||||
void ExpectErrorSubstringWithZeroReturnCode(
|
||||
const string& expected_substring);
|
||||
|
||||
// Checks that the captured stdout is the same as the expected_text.
|
||||
void ExpectCapturedStdout(const string& expected_text);
|
||||
|
||||
// Returns true if ExpectErrorSubstring(expected_substring) would pass, but
|
||||
// does not fail otherwise.
|
||||
bool HasAlternateErrorSubstring(const string& expected_substring);
|
||||
@@ -163,6 +193,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_;
|
||||
@@ -182,8 +215,11 @@ class CommandLineInterfaceTest : public testing::Test {
|
||||
// The captured stderr output.
|
||||
string error_text_;
|
||||
|
||||
// The captured stdout.
|
||||
string captured_stdout_;
|
||||
|
||||
// Pointers which need to be deleted later.
|
||||
vector<CodeGenerator*> mock_generators_to_delete_;
|
||||
std::vector<CodeGenerator*> mock_generators_to_delete_;
|
||||
|
||||
NullCodeGenerator* null_generator_;
|
||||
};
|
||||
@@ -219,12 +255,12 @@ void CommandLineInterfaceTest::SetUp() {
|
||||
|
||||
// If the temp directory already exists, it must be left over from a
|
||||
// previous run. Delete it.
|
||||
if (File::Exists(temp_directory_)) {
|
||||
if (FileExists(temp_directory_)) {
|
||||
File::DeleteRecursively(temp_directory_, NULL, NULL);
|
||||
}
|
||||
|
||||
// Create the temp directory.
|
||||
GOOGLE_CHECK(File::CreateDir(temp_directory_.c_str(), DEFAULT_FILE_MODE));
|
||||
GOOGLE_CHECK_OK(File::CreateDir(temp_directory_, 0777));
|
||||
|
||||
// Register generators.
|
||||
CodeGenerator* generator = new MockCodeGenerator("test_generator");
|
||||
@@ -245,7 +281,9 @@ void CommandLineInterfaceTest::SetUp() {
|
||||
|
||||
void CommandLineInterfaceTest::TearDown() {
|
||||
// Delete the temp directory.
|
||||
File::DeleteRecursively(temp_directory_, NULL, NULL);
|
||||
if (FileExists(temp_directory_)) {
|
||||
File::DeleteRecursively(temp_directory_, NULL, NULL);
|
||||
}
|
||||
|
||||
// Delete all the MockCodeGenerators.
|
||||
for (int i = 0; i < mock_generators_to_delete_.size(); i++) {
|
||||
@@ -255,11 +293,17 @@ void CommandLineInterfaceTest::TearDown() {
|
||||
}
|
||||
|
||||
void CommandLineInterfaceTest::Run(const string& command) {
|
||||
vector<string> args;
|
||||
SplitStringUsing(command, " ", &args);
|
||||
RunWithArgs(Split(command, " ", true));
|
||||
}
|
||||
|
||||
void CommandLineInterfaceTest::RunWithArgs(vector<string> args) {
|
||||
if (!disallow_plugins_) {
|
||||
cli_.AllowPlugins("prefix-");
|
||||
#ifndef GOOGLE_THIRD_PARTY_PROTOBUF
|
||||
string plugin_path;
|
||||
#ifdef GOOGLE_PROTOBUF_TEST_PLUGIN_PATH
|
||||
plugin_path = GOOGLE_PROTOBUF_TEST_PLUGIN_PATH;
|
||||
#else
|
||||
const char* possible_paths[] = {
|
||||
// When building with shared libraries, libtool hides the real executable
|
||||
// in .libs and puts a fake wrapper in the current directory.
|
||||
@@ -277,17 +321,20 @@ void CommandLineInterfaceTest::Run(const string& command) {
|
||||
"test_plugin.exe", // Other Win32 (MSVC)
|
||||
"test_plugin", // Unix
|
||||
};
|
||||
|
||||
string plugin_path;
|
||||
|
||||
for (int i = 0; i < GOOGLE_ARRAYSIZE(possible_paths); i++) {
|
||||
if (access(possible_paths[i], F_OK) == 0) {
|
||||
plugin_path = possible_paths[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (plugin_path.empty()) {
|
||||
#else
|
||||
string plugin_path = "third_party/protobuf/test_plugin";
|
||||
|
||||
if (access(plugin_path.c_str(), F_OK) != 0) {
|
||||
#endif // GOOGLE_THIRD_PARTY_PROTOBUF
|
||||
GOOGLE_LOG(ERROR)
|
||||
<< "Plugin executable not found. Plugin tests are likely to fail.";
|
||||
} else {
|
||||
@@ -295,18 +342,27 @@ void CommandLineInterfaceTest::Run(const string& command) {
|
||||
}
|
||||
}
|
||||
|
||||
scoped_array<const char*> argv(new const char*[args.size()]);
|
||||
google::protobuf::scoped_array<const char * > argv(new const char* [args.size()]);
|
||||
|
||||
for (int i = 0; i < args.size(); i++) {
|
||||
args[i] = StringReplace(args[i], "$tmpdir", temp_directory_, true);
|
||||
argv[i] = args[i].c_str();
|
||||
}
|
||||
|
||||
// TODO(jieluo): Cygwin doesn't work well if we try to capture stderr and
|
||||
// stdout at the same time. Need to figure out why and add this capture back
|
||||
// for Cygwin.
|
||||
#if !defined(__CYGWIN__)
|
||||
CaptureTestStdout();
|
||||
#endif
|
||||
CaptureTestStderr();
|
||||
|
||||
return_code_ = cli_.Run(args.size(), argv.get());
|
||||
|
||||
error_text_ = GetCapturedTestStderr();
|
||||
#if !defined(__CYGWIN__)
|
||||
captured_stdout_ = GetCapturedTestStdout();
|
||||
#endif
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
@@ -318,16 +374,22 @@ void CommandLineInterfaceTest::CreateTempFile(
|
||||
string::size_type slash_pos = name.find_last_of('/');
|
||||
if (slash_pos != string::npos) {
|
||||
string dir = name.substr(0, slash_pos);
|
||||
File::RecursivelyCreateDir(temp_directory_ + "/" + dir, 0777);
|
||||
if (!FileExists(temp_directory_ + "/" + dir)) {
|
||||
GOOGLE_CHECK_OK(File::RecursivelyCreateDir(temp_directory_ + "/" + dir,
|
||||
0777));
|
||||
}
|
||||
}
|
||||
|
||||
// Write file.
|
||||
string full_name = temp_directory_ + "/" + name;
|
||||
File::WriteStringToFileOrDie(contents, full_name);
|
||||
GOOGLE_CHECK_OK(File::SetContents(
|
||||
full_name, StringReplace(contents, "$tmpdir", temp_directory_, true),
|
||||
true));
|
||||
}
|
||||
|
||||
void CommandLineInterfaceTest::CreateTempDir(const string& name) {
|
||||
File::RecursivelyCreateDir(temp_directory_ + "/" + name, 0777);
|
||||
GOOGLE_CHECK_OK(File::RecursivelyCreateDir(temp_directory_ + "/" + name,
|
||||
0777));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
@@ -414,14 +476,29 @@ void CommandLineInterfaceTest::ReadDescriptorSet(
|
||||
const string& filename, FileDescriptorSet* descriptor_set) {
|
||||
string path = temp_directory_ + "/" + filename;
|
||||
string file_contents;
|
||||
if (!File::ReadFileToString(path, &file_contents)) {
|
||||
FAIL() << "File not found: " << path;
|
||||
}
|
||||
GOOGLE_CHECK_OK(File::GetContents(path, &file_contents, true));
|
||||
|
||||
if (!descriptor_set->ParseFromString(file_contents)) {
|
||||
FAIL() << "Could not parse file contents: " << path;
|
||||
}
|
||||
}
|
||||
|
||||
void CommandLineInterfaceTest::ExpectCapturedStdout(
|
||||
const string& expected_text) {
|
||||
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) {
|
||||
@@ -580,6 +657,44 @@ TEST_F(CommandLineInterfaceTest, ExtraGeneratorParameters) {
|
||||
"test_generator", "baz,foo1,foo2,foo3", "foo.proto", "Foo", "b");
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, ExtraPluginParameters) {
|
||||
// Test that generator parameters specified with the option flag are
|
||||
// correctly passed to the code generator.
|
||||
|
||||
CreateTempFile("foo.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"message Foo {}\n");
|
||||
// Create the "a" and "b" sub-directories.
|
||||
CreateTempDir("a");
|
||||
CreateTempDir("b");
|
||||
|
||||
Run("protocol_compiler "
|
||||
"--plug_opt=foo1 "
|
||||
"--plug_out=bar:$tmpdir/a "
|
||||
"--plug_opt=foo2 "
|
||||
"--plug_out=baz:$tmpdir/b "
|
||||
"--plug_opt=foo3 "
|
||||
"--proto_path=$tmpdir foo.proto");
|
||||
|
||||
ExpectNoErrors();
|
||||
ExpectGenerated(
|
||||
"test_plugin", "bar,foo1,foo2,foo3", "foo.proto", "Foo", "a");
|
||||
ExpectGenerated(
|
||||
"test_plugin", "baz,foo1,foo2,foo3", "foo.proto", "Foo", "b");
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, UnrecognizedExtraParameters) {
|
||||
CreateTempFile("foo.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"message Foo {}\n");
|
||||
|
||||
Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
|
||||
"--unknown_plug_opt=Foo "
|
||||
"--proto_path=$tmpdir foo.proto");
|
||||
|
||||
ExpectErrorSubstring("Unknown flag: --unknown_plug_opt");
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, Insert) {
|
||||
// Test running a generator that inserts code into another's output.
|
||||
|
||||
@@ -646,6 +761,11 @@ TEST_F(CommandLineInterfaceTest, TrailingBackslash) {
|
||||
ExpectGenerated("test_generator", "", "foo.proto", "Foo");
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, Win32ErrorMessage) {
|
||||
EXPECT_EQ("The system cannot find the file specified.\r\n",
|
||||
Subprocess::Win32ErrorMessage(ERROR_FILE_NOT_FOUND));
|
||||
}
|
||||
|
||||
#endif // defined(_WIN32) || defined(__CYGWIN__)
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, PathLookup) {
|
||||
@@ -691,7 +811,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
|
||||
|
||||
@@ -713,6 +833,21 @@ TEST_F(CommandLineInterfaceTest, NonRootMapping) {
|
||||
ExpectGenerated("test_generator", "", "bar/foo.proto", "Foo");
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, PathWithEqualsSign) {
|
||||
// Test setting up a search path which happens to have '=' in it.
|
||||
|
||||
CreateTempDir("with=sign");
|
||||
CreateTempFile("with=sign/foo.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"message Foo {}\n");
|
||||
|
||||
Run("protocol_compiler --test_out=$tmpdir "
|
||||
"--proto_path=$tmpdir/with=sign foo.proto");
|
||||
|
||||
ExpectNoErrors();
|
||||
ExpectGenerated("test_generator", "", "foo.proto", "Foo");
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, MultipleGenerators) {
|
||||
// Test that we can have multiple generators and use both in one invocation,
|
||||
// each with a different output directory.
|
||||
@@ -778,6 +913,113 @@ TEST_F(CommandLineInterfaceTest, AllowServicesHasService) {
|
||||
ExpectGenerated("test_generator", "", "foo.proto", "Foo");
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, DirectDependencies_Missing_EmptyList) {
|
||||
CreateTempFile("foo.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"import \"bar.proto\";\n"
|
||||
"message Foo { optional Bar bar = 1; }");
|
||||
CreateTempFile("bar.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"message Bar { optional string text = 1; }");
|
||||
|
||||
Run("protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
|
||||
"--direct_dependencies= foo.proto");
|
||||
|
||||
ExpectErrorText(
|
||||
"foo.proto: File is imported but not declared in --direct_dependencies: "
|
||||
"bar.proto\n");
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, DirectDependencies_Missing) {
|
||||
CreateTempFile("foo.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"import \"bar.proto\";\n"
|
||||
"import \"bla.proto\";\n"
|
||||
"message Foo { optional Bar bar = 1; optional Bla bla = 2; }");
|
||||
CreateTempFile("bar.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"message Bar { optional string text = 1; }");
|
||||
CreateTempFile("bla.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"message Bla { optional int64 number = 1; }");
|
||||
|
||||
Run("protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
|
||||
"--direct_dependencies=bla.proto foo.proto");
|
||||
|
||||
ExpectErrorText(
|
||||
"foo.proto: File is imported but not declared in --direct_dependencies: "
|
||||
"bar.proto\n");
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, DirectDependencies_NoViolation) {
|
||||
CreateTempFile("foo.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"import \"bar.proto\";\n"
|
||||
"message Foo { optional Bar bar = 1; }");
|
||||
CreateTempFile("bar.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"message Bar { optional string text = 1; }");
|
||||
|
||||
Run("protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
|
||||
"--direct_dependencies=bar.proto foo.proto");
|
||||
|
||||
ExpectNoErrors();
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, DirectDependencies_NoViolation_MultiImports) {
|
||||
CreateTempFile("foo.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"import \"bar.proto\";\n"
|
||||
"import \"bla.proto\";\n"
|
||||
"message Foo { optional Bar bar = 1; optional Bla bla = 2; }");
|
||||
CreateTempFile("bar.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"message Bar { optional string text = 1; }");
|
||||
CreateTempFile("bla.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"message Bla { optional int64 number = 1; }");
|
||||
|
||||
Run("protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
|
||||
"--direct_dependencies=bar.proto:bla.proto foo.proto");
|
||||
|
||||
ExpectNoErrors();
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, DirectDependencies_ProvidedMultipleTimes) {
|
||||
CreateTempFile("foo.proto",
|
||||
"syntax = \"proto2\";\n");
|
||||
|
||||
Run("protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
|
||||
"--direct_dependencies=bar.proto --direct_dependencies=bla.proto "
|
||||
"foo.proto");
|
||||
|
||||
ExpectErrorText(
|
||||
"--direct_dependencies may only be passed once. To specify multiple "
|
||||
"direct dependencies, pass them all as a single parameter separated by "
|
||||
"':'.\n");
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, DirectDependencies_CustomErrorMessage) {
|
||||
CreateTempFile("foo.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"import \"bar.proto\";\n"
|
||||
"message Foo { optional Bar bar = 1; }");
|
||||
CreateTempFile("bar.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"message Bar { optional string text = 1; }");
|
||||
|
||||
vector<string> commands;
|
||||
commands.push_back("protocol_compiler");
|
||||
commands.push_back("--test_out=$tmpdir");
|
||||
commands.push_back("--proto_path=$tmpdir");
|
||||
commands.push_back("--direct_dependencies=");
|
||||
commands.push_back("--direct_dependencies_violation_msg=Bla \"%s\" Bla");
|
||||
commands.push_back("foo.proto");
|
||||
RunWithArgs(commands);
|
||||
|
||||
ExpectErrorText("foo.proto: Bla \"bar.proto\" Bla\n");
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, CwdRelativeInputs) {
|
||||
// Test that we can accept working-directory-relative input files.
|
||||
|
||||
@@ -813,10 +1055,51 @@ TEST_F(CommandLineInterfaceTest, WriteDescriptorSet) {
|
||||
FileDescriptorSet descriptor_set;
|
||||
ReadDescriptorSet("descriptor_set", &descriptor_set);
|
||||
if (HasFatalFailure()) return;
|
||||
ASSERT_EQ(1, descriptor_set.file_size());
|
||||
EXPECT_EQ(1, descriptor_set.file_size());
|
||||
EXPECT_EQ("bar.proto", descriptor_set.file(0).name());
|
||||
// Descriptor set should not have source code info.
|
||||
EXPECT_FALSE(descriptor_set.file(0).has_source_code_info());
|
||||
// Descriptor set should have json_name.
|
||||
EXPECT_EQ("Bar", descriptor_set.file(0).message_type(0).name());
|
||||
EXPECT_EQ("foo", descriptor_set.file(0).message_type(0).field(0).name());
|
||||
EXPECT_TRUE(descriptor_set.file(0).message_type(0).field(0).has_json_name());
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithDuplicates) {
|
||||
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");
|
||||
CreateTempFile("baz.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"import \"foo.proto\";\n"
|
||||
"message Baz {\n"
|
||||
" optional Foo foo = 1;\n"
|
||||
"}\n");
|
||||
|
||||
Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
|
||||
"--proto_path=$tmpdir bar.proto foo.proto bar.proto baz.proto");
|
||||
|
||||
ExpectNoErrors();
|
||||
|
||||
FileDescriptorSet descriptor_set;
|
||||
ReadDescriptorSet("descriptor_set", &descriptor_set);
|
||||
if (HasFatalFailure()) return;
|
||||
EXPECT_EQ(3, descriptor_set.file_size());
|
||||
EXPECT_EQ("bar.proto", descriptor_set.file(0).name());
|
||||
EXPECT_EQ("foo.proto", descriptor_set.file(1).name());
|
||||
EXPECT_EQ("baz.proto", descriptor_set.file(2).name());
|
||||
// Descriptor set should not have source code info.
|
||||
EXPECT_FALSE(descriptor_set.file(0).has_source_code_info());
|
||||
// Descriptor set should have json_name.
|
||||
EXPECT_EQ("Bar", descriptor_set.file(0).message_type(0).name());
|
||||
EXPECT_EQ("foo", descriptor_set.file(0).message_type(0).field(0).name());
|
||||
EXPECT_TRUE(descriptor_set.file(0).message_type(0).field(0).has_json_name());
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) {
|
||||
@@ -838,7 +1121,7 @@ TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) {
|
||||
FileDescriptorSet descriptor_set;
|
||||
ReadDescriptorSet("descriptor_set", &descriptor_set);
|
||||
if (HasFatalFailure()) return;
|
||||
ASSERT_EQ(1, descriptor_set.file_size());
|
||||
EXPECT_EQ(1, descriptor_set.file_size());
|
||||
EXPECT_EQ("bar.proto", descriptor_set.file(0).name());
|
||||
// Source code info included.
|
||||
EXPECT_TRUE(descriptor_set.file(0).has_source_code_info());
|
||||
@@ -863,7 +1146,7 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) {
|
||||
FileDescriptorSet descriptor_set;
|
||||
ReadDescriptorSet("descriptor_set", &descriptor_set);
|
||||
if (HasFatalFailure()) return;
|
||||
ASSERT_EQ(2, descriptor_set.file_size());
|
||||
EXPECT_EQ(2, descriptor_set.file_size());
|
||||
if (descriptor_set.file(0).name() == "bar.proto") {
|
||||
std::swap(descriptor_set.mutable_file()->mutable_data()[0],
|
||||
descriptor_set.mutable_file()->mutable_data()[1]);
|
||||
@@ -894,7 +1177,7 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) {
|
||||
FileDescriptorSet descriptor_set;
|
||||
ReadDescriptorSet("descriptor_set", &descriptor_set);
|
||||
if (HasFatalFailure()) return;
|
||||
ASSERT_EQ(2, descriptor_set.file_size());
|
||||
EXPECT_EQ(2, descriptor_set.file_size());
|
||||
if (descriptor_set.file(0).name() == "bar.proto") {
|
||||
std::swap(descriptor_set.mutable_file()->mutable_data()[0],
|
||||
descriptor_set.mutable_file()->mutable_data()[1]);
|
||||
@@ -906,6 +1189,81 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) {
|
||||
EXPECT_TRUE(descriptor_set.file(1).has_source_code_info());
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// TODO(teboring): Figure out how to write test on windows.
|
||||
#else
|
||||
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");
|
||||
}
|
||||
|
||||
#ifdef PROTOBUF_OPENSOURCE
|
||||
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);
|
||||
}
|
||||
#else // !PROTOBUF_OPENSOURCE
|
||||
// TODO(teboring): Figure out how to change and get working directory in
|
||||
// google3.
|
||||
#endif // !PROTOBUF_OPENSOURCE
|
||||
|
||||
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");
|
||||
}
|
||||
#endif // !_WIN32
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, ParseErrors) {
|
||||
@@ -949,6 +1307,19 @@ TEST_F(CommandLineInterfaceTest, ParseErrorsMultipleFiles) {
|
||||
"foo.proto: Import \"baz.proto\" was not found or had errors.\n");
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, RecursiveImportFails) {
|
||||
// Create a proto file that imports itself.
|
||||
CreateTempFile("foo.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"import \"foo.proto\";\n");
|
||||
|
||||
Run("protocol_compiler --test_out=$tmpdir "
|
||||
"--proto_path=$tmpdir foo.proto");
|
||||
|
||||
ExpectErrorSubstring(
|
||||
"foo.proto: File recursively imports itself: foo.proto -> foo.proto\n");
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, InputNotFoundError) {
|
||||
// Test what happens if the input file is not found.
|
||||
|
||||
@@ -1237,6 +1608,33 @@ TEST_F(CommandLineInterfaceTest, PluginReceivesSourceCodeInfo) {
|
||||
"Saw message type MockCodeGenerator_HasSourceCodeInfo: 1.");
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, PluginReceivesJsonName) {
|
||||
CreateTempFile("foo.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"message MockCodeGenerator_HasJsonName {\n"
|
||||
" optional int32 value = 1;\n"
|
||||
"}\n");
|
||||
|
||||
Run("protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto");
|
||||
|
||||
ExpectErrorSubstring("Saw json_name: 1");
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, PluginReceivesCompilerVersion) {
|
||||
CreateTempFile("foo.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"message MockCodeGenerator_ShowVersionNumber {\n"
|
||||
" optional int32 value = 1;\n"
|
||||
"}\n");
|
||||
|
||||
Run("protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto");
|
||||
|
||||
ExpectErrorSubstring(
|
||||
StringPrintf("Saw compiler_version: %d %s",
|
||||
GOOGLE_PROTOBUF_VERSION,
|
||||
GOOGLE_PROTOBUF_VERSION_SUFFIX));
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) {
|
||||
// Test what happens if the plugin isn't found.
|
||||
|
||||
@@ -1393,6 +1791,76 @@ TEST_F(CommandLineInterfaceTest, MissingValueAtEndError) {
|
||||
ExpectErrorText("Missing value for flag: --test_out\n");
|
||||
}
|
||||
|
||||
TEST_F(CommandLineInterfaceTest, PrintFreeFieldNumbers) {
|
||||
CreateTempFile(
|
||||
"foo.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"package foo;\n"
|
||||
"message Foo {\n"
|
||||
" optional int32 a = 2;\n"
|
||||
" optional string b = 4;\n"
|
||||
" optional string c = 5;\n"
|
||||
" optional int64 d = 8;\n"
|
||||
" optional double e = 10;\n"
|
||||
"}\n");
|
||||
CreateTempFile(
|
||||
"bar.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"message Bar {\n"
|
||||
" optional int32 a = 2;\n"
|
||||
" extensions 4 to 5;\n"
|
||||
" optional int64 d = 8;\n"
|
||||
" extensions 10;\n"
|
||||
"}\n");
|
||||
CreateTempFile(
|
||||
"baz.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"message Baz {\n"
|
||||
" optional int32 a = 2;\n"
|
||||
" optional int64 d = 8;\n"
|
||||
" extensions 15 to max;\n" // unordered.
|
||||
" extensions 13;\n"
|
||||
" extensions 10 to 12;\n"
|
||||
" extensions 5;\n"
|
||||
" extensions 4;\n"
|
||||
"}\n");
|
||||
CreateTempFile(
|
||||
"quz.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"message Quz {\n"
|
||||
" message Foo {}\n" // nested message
|
||||
" optional int32 a = 2;\n"
|
||||
" optional group C = 4 {\n"
|
||||
" optional int32 d = 5;\n"
|
||||
" }\n"
|
||||
" extensions 8 to 10;\n"
|
||||
" optional group E = 11 {\n"
|
||||
" optional int32 f = 9;\n" // explicitly reuse extension range 8-10
|
||||
" optional group G = 15 {\n" // nested group
|
||||
" message Foo {}\n" // nested message inside nested group
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
|
||||
Run("protocol_compiler --print_free_field_numbers --proto_path=$tmpdir "
|
||||
"foo.proto bar.proto baz.proto quz.proto");
|
||||
|
||||
ExpectNoErrors();
|
||||
|
||||
// TODO(jieluo): Cygwin doesn't work well if we try to capture stderr and
|
||||
// stdout at the same time. Need to figure out why and add this test back
|
||||
// for Cygwin.
|
||||
#if !defined(__CYGWIN__)
|
||||
ExpectCapturedStdout(
|
||||
"foo.Foo free: 1 3 6-7 9 11-INF\n"
|
||||
"Bar free: 1 3 6-7 9 11-INF\n"
|
||||
"Baz free: 1 3 6-7 9 14\n"
|
||||
"Quz.Foo free: 1-INF\n"
|
||||
"Quz.E.G.Foo free: 1-INF\n"
|
||||
"Quz free: 1 3 6-7 12-14 16-INF\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// Test for --encode and --decode. Note that it would be easier to do this
|
||||
@@ -1412,7 +1880,7 @@ class EncodeDecodeTest : public testing::Test {
|
||||
|
||||
void RedirectStdinFromText(const string& input) {
|
||||
string filename = TestTempDir() + "/test_stdin";
|
||||
File::WriteStringToFileOrDie(input, filename);
|
||||
GOOGLE_CHECK_OK(File::SetContents(filename, input, true));
|
||||
GOOGLE_CHECK(RedirectStdinFromFile(filename));
|
||||
}
|
||||
|
||||
@@ -1441,12 +1909,12 @@ class EncodeDecodeTest : public testing::Test {
|
||||
enum ReturnCode { SUCCESS, ERROR };
|
||||
|
||||
bool Run(const string& command) {
|
||||
vector<string> args;
|
||||
std::vector<string> args;
|
||||
args.push_back("protoc");
|
||||
SplitStringUsing(command, " ", &args);
|
||||
args.push_back("--proto_path=" + TestSourceDir());
|
||||
|
||||
scoped_array<const char*> argv(new const char*[args.size()]);
|
||||
google::protobuf::scoped_array<const char * > argv(new const char* [args.size()]);
|
||||
for (int i = 0; i < args.size(); i++) {
|
||||
argv[i] = args[i].c_str();
|
||||
}
|
||||
@@ -1467,7 +1935,7 @@ class EncodeDecodeTest : public testing::Test {
|
||||
|
||||
void ExpectStdoutMatchesBinaryFile(const string& filename) {
|
||||
string expected_output;
|
||||
ASSERT_TRUE(File::ReadFileToString(filename, &expected_output));
|
||||
GOOGLE_CHECK_OK(File::GetContents(filename, &expected_output, true));
|
||||
|
||||
// Don't use EXPECT_EQ because we don't want to print raw binary data to
|
||||
// stdout on failure.
|
||||
@@ -1476,7 +1944,7 @@ class EncodeDecodeTest : public testing::Test {
|
||||
|
||||
void ExpectStdoutMatchesTextFile(const string& filename) {
|
||||
string expected_output;
|
||||
ASSERT_TRUE(File::ReadFileToString(filename, &expected_output));
|
||||
GOOGLE_CHECK_OK(File::GetContents(filename, &expected_output, true));
|
||||
|
||||
ExpectStdoutMatchesText(expected_output);
|
||||
}
|
||||
@@ -1496,22 +1964,23 @@ class EncodeDecodeTest : public testing::Test {
|
||||
};
|
||||
|
||||
TEST_F(EncodeDecodeTest, Encode) {
|
||||
RedirectStdinFromFile(TestSourceDir() +
|
||||
"/google/protobuf/testdata/text_format_unittest_data.txt");
|
||||
RedirectStdinFromFile(TestSourceDir() + "/google/protobuf/"
|
||||
"testdata/text_format_unittest_data_oneof_implemented.txt");
|
||||
EXPECT_TRUE(Run("google/protobuf/unittest.proto "
|
||||
"--encode=protobuf_unittest.TestAllTypes"));
|
||||
ExpectStdoutMatchesBinaryFile(TestSourceDir() +
|
||||
"/google/protobuf/testdata/golden_message");
|
||||
"/google/protobuf/testdata/golden_message_oneof_implemented");
|
||||
ExpectStderrMatchesText("");
|
||||
}
|
||||
|
||||
TEST_F(EncodeDecodeTest, Decode) {
|
||||
RedirectStdinFromFile(TestSourceDir() +
|
||||
"/google/protobuf/testdata/golden_message");
|
||||
"/google/protobuf/testdata/golden_message_oneof_implemented");
|
||||
EXPECT_TRUE(Run("google/protobuf/unittest.proto "
|
||||
"--decode=protobuf_unittest.TestAllTypes"));
|
||||
ExpectStdoutMatchesTextFile(TestSourceDir() +
|
||||
"/google/protobuf/testdata/text_format_unittest_data.txt");
|
||||
"/google/protobuf/"
|
||||
"testdata/text_format_unittest_data_oneof_implemented.txt");
|
||||
ExpectStderrMatchesText("");
|
||||
}
|
||||
|
||||
@@ -1555,6 +2024,8 @@ TEST_F(EncodeDecodeTest, ProtoParseError) {
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
#endif // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
+10
-10
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -48,11 +48,12 @@
|
||||
#include <google/protobuf/compiler/importer.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
#include <google/protobuf/stubs/map-util.h>
|
||||
#include <google/protobuf/stubs/map_util.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/stubs/substitute.h>
|
||||
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/testing/googletest.h>
|
||||
#include <gtest/gtest.h>
|
||||
@@ -93,12 +94,12 @@ class MockGeneratorContext : public GeneratorContext {
|
||||
<< "Generator failed to generate file: " << virtual_filename;
|
||||
|
||||
string actual_contents;
|
||||
File::ReadFileToStringOrDie(
|
||||
TestSourceDir() + "/" + physical_filename,
|
||||
&actual_contents);
|
||||
GOOGLE_CHECK_OK(
|
||||
File::GetContents(TestSourceDir() + "/" + physical_filename,
|
||||
&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 "
|
||||
"generate_descriptor_proto.sh. Then add this file "
|
||||
"to your CL.";
|
||||
}
|
||||
|
||||
@@ -106,14 +107,14 @@ class MockGeneratorContext : public GeneratorContext {
|
||||
|
||||
virtual io::ZeroCopyOutputStream* Open(const string& filename) {
|
||||
string** map_slot = &files_[filename];
|
||||
if (*map_slot != NULL) delete *map_slot;
|
||||
delete *map_slot;
|
||||
*map_slot = new string;
|
||||
|
||||
return new io::StringOutputStream(*map_slot);
|
||||
}
|
||||
|
||||
private:
|
||||
map<string, string*> files_;
|
||||
std::map<string, string*> files_;
|
||||
};
|
||||
|
||||
TEST(BootstrapTest, GeneratedDescriptorMatches) {
|
||||
@@ -132,8 +133,7 @@ TEST(BootstrapTest, GeneratedDescriptorMatches) {
|
||||
CppGenerator generator;
|
||||
MockGeneratorContext context;
|
||||
string error;
|
||||
string parameter;
|
||||
parameter = "dllexport_decl=LIBPROTOBUF_EXPORT";
|
||||
string parameter = "dllexport_decl=LIBPROTOBUF_EXPORT";
|
||||
ASSERT_TRUE(generator.Generate(proto_file, parameter,
|
||||
&context, &error));
|
||||
parameter = "dllexport_decl=LIBPROTOC_EXPORT";
|
||||
+122
-56
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -32,7 +32,6 @@
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_enum.h>
|
||||
@@ -45,34 +44,65 @@ namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
namespace {
|
||||
// The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value
|
||||
// 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();
|
||||
for (int i = 0; i < descriptor->value_count(); i++) {
|
||||
if (descriptor->value(i)->number() > max_value) {
|
||||
max_value = descriptor->value(i)->number();
|
||||
}
|
||||
}
|
||||
return max_value != ::google::protobuf::kint32max;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: descriptor_(descriptor),
|
||||
classname_(ClassName(descriptor, false)),
|
||||
options_(options) {
|
||||
options_(options),
|
||||
generate_array_size_(ShouldGenerateArraySize(descriptor)) {
|
||||
}
|
||||
|
||||
EnumGenerator::~EnumGenerator() {}
|
||||
|
||||
void EnumGenerator::FillForwardDeclaration(
|
||||
std::map<string, const EnumDescriptor*>* enum_names) {
|
||||
if (!options_.proto_h) {
|
||||
return;
|
||||
}
|
||||
(*enum_names)[classname_] = descriptor_;
|
||||
}
|
||||
|
||||
void EnumGenerator::GenerateDefinition(io::Printer* printer) {
|
||||
map<string, string> vars;
|
||||
std::map<string, string> vars;
|
||||
vars["classname"] = classname_;
|
||||
vars["short_name"] = descriptor_->name();
|
||||
vars["enumbase"] = classname_ + (options_.proto_h ? " : int" : "");
|
||||
|
||||
printer->Print(vars, "enum $classname$ {\n");
|
||||
printer->Print(vars, "enum $enumbase$ {\n");
|
||||
printer->Annotate("enumbase", descriptor_);
|
||||
printer->Indent();
|
||||
|
||||
const EnumValueDescriptor* min_value = descriptor_->value(0);
|
||||
const EnumValueDescriptor* max_value = descriptor_->value(0);
|
||||
|
||||
for (int i = 0; i < descriptor_->value_count(); i++) {
|
||||
vars["name"] = descriptor_->value(i)->name();
|
||||
vars["number"] = SimpleItoa(descriptor_->value(i)->number());
|
||||
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.
|
||||
vars["number"] = Int32ToString(descriptor_->value(i)->number());
|
||||
vars["prefix"] = (descriptor_->containing_type() == NULL) ?
|
||||
"" : classname_ + "_";
|
||||
vars["deprecation"] = descriptor_->value(i)->options().deprecated() ?
|
||||
" PROTOBUF_DEPRECATED" : "";
|
||||
|
||||
if (i > 0) printer->Print(",\n");
|
||||
printer->Print(vars, "$prefix$$name$ = $number$");
|
||||
printer->Print(vars, "$prefix$$name$$deprecation$ = $number$");
|
||||
|
||||
if (descriptor_->value(i)->number() < min_value->number()) {
|
||||
min_value = descriptor_->value(i);
|
||||
@@ -82,11 +112,20 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
|
||||
}
|
||||
}
|
||||
|
||||
if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
|
||||
// For new enum semantics: generate min and max sentinel values equal to
|
||||
// INT32_MIN and INT32_MAX
|
||||
if (descriptor_->value_count() > 0) printer->Print(",\n");
|
||||
printer->Print(vars,
|
||||
"$classname$_$prefix$INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min,\n"
|
||||
"$classname$_$prefix$INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max");
|
||||
}
|
||||
|
||||
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"] = "";
|
||||
@@ -97,19 +136,24 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
|
||||
printer->Print(vars,
|
||||
"$dllexport$bool $classname$_IsValid(int value);\n"
|
||||
"const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n"
|
||||
"const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n"
|
||||
"const int $prefix$$short_name$_ARRAYSIZE = $prefix$$short_name$_MAX + 1;\n"
|
||||
"\n");
|
||||
"const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n");
|
||||
|
||||
if (HasDescriptorMethods(descriptor_->file())) {
|
||||
if (generate_array_size_) {
|
||||
printer->Print(vars,
|
||||
"const int $prefix$$short_name$_ARRAYSIZE = "
|
||||
"$prefix$$short_name$_MAX + 1;\n\n");
|
||||
}
|
||||
|
||||
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||
printer->Print(vars,
|
||||
"$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n");
|
||||
// The _Name and _Parse methods
|
||||
printer->Print(vars,
|
||||
"inline const ::std::string& $classname$_Name($classname$ value) {\n"
|
||||
" return ::google::protobuf::internal::NameOfEnum(\n"
|
||||
" $classname$_descriptor(), value);\n"
|
||||
"}\n");
|
||||
printer->Print(
|
||||
vars,
|
||||
"inline const ::std::string& $classname$_Name($classname$ value) {\n"
|
||||
" return ::google::protobuf::internal::NameOfEnum(\n"
|
||||
" $classname$_descriptor(), value);\n"
|
||||
"}\n");
|
||||
printer->Print(vars,
|
||||
"inline bool $classname$_Parse(\n"
|
||||
" const ::std::string& name, $classname$* value) {\n"
|
||||
@@ -121,7 +165,11 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
|
||||
|
||||
void EnumGenerator::
|
||||
GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
|
||||
if (HasDescriptorMethods(descriptor_->file())) {
|
||||
printer->Print(
|
||||
"template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type "
|
||||
"{};\n",
|
||||
"classname", ClassName(descriptor_, true));
|
||||
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||
printer->Print(
|
||||
"template <>\n"
|
||||
"inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n"
|
||||
@@ -132,15 +180,19 @@ GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
|
||||
}
|
||||
|
||||
void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
|
||||
map<string, string> vars;
|
||||
std::map<string, string> vars;
|
||||
vars["nested_name"] = descriptor_->name();
|
||||
vars["classname"] = classname_;
|
||||
vars["constexpr"] = options_.proto_h ? "constexpr " : "";
|
||||
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));
|
||||
vars["deprecated_attr"] = descriptor_->value(j)->options().deprecated() ?
|
||||
"GOOGLE_PROTOBUF_DEPRECATED_ATTR " : "";
|
||||
printer->Print(vars,
|
||||
"static const $nested_name$ $tag$ = $classname$_$tag$;\n");
|
||||
"$deprecated_attr$static $constexpr$const $nested_name$ $tag$ =\n"
|
||||
" $classname$_$tag$;\n");
|
||||
}
|
||||
|
||||
printer->Print(vars,
|
||||
@@ -150,20 +202,25 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
|
||||
"static const $nested_name$ $nested_name$_MIN =\n"
|
||||
" $classname$_$nested_name$_MIN;\n"
|
||||
"static const $nested_name$ $nested_name$_MAX =\n"
|
||||
" $classname$_$nested_name$_MAX;\n"
|
||||
"static const int $nested_name$_ARRAYSIZE =\n"
|
||||
" $classname$_$nested_name$_ARRAYSIZE;\n");
|
||||
" $classname$_$nested_name$_MAX;\n");
|
||||
if (generate_array_size_) {
|
||||
printer->Print(vars,
|
||||
"static const int $nested_name$_ARRAYSIZE =\n"
|
||||
" $classname$_$nested_name$_ARRAYSIZE;\n");
|
||||
}
|
||||
|
||||
if (HasDescriptorMethods(descriptor_->file())) {
|
||||
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||
printer->Print(vars,
|
||||
"static inline const ::google::protobuf::EnumDescriptor*\n"
|
||||
"$nested_name$_descriptor() {\n"
|
||||
" return $classname$_descriptor();\n"
|
||||
"}\n");
|
||||
printer->Print(vars,
|
||||
"static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n"
|
||||
" return $classname$_Name(value);\n"
|
||||
"}\n");
|
||||
"static inline const ::std::string& "
|
||||
"$nested_name$_Name($nested_name$ value) {"
|
||||
"\n"
|
||||
" return $classname$_Name(value);\n"
|
||||
"}\n");
|
||||
printer->Print(vars,
|
||||
"static inline bool $nested_name$_Parse(const ::std::string& name,\n"
|
||||
" $nested_name$* value) {\n"
|
||||
@@ -172,53 +229,59 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
|
||||
}
|
||||
}
|
||||
|
||||
void EnumGenerator::GenerateDescriptorInitializer(
|
||||
io::Printer* printer, int index) {
|
||||
map<string, string> vars;
|
||||
vars["classname"] = classname_;
|
||||
vars["index"] = SimpleItoa(index);
|
||||
void EnumGenerator::GenerateDescriptorInitializer(io::Printer* printer) {
|
||||
std::map<string, string> vars;
|
||||
vars["index"] = SimpleItoa(descriptor_->index());
|
||||
vars["index_in_metadata"] = SimpleItoa(index_in_metadata_);
|
||||
|
||||
if (descriptor_->containing_type() == NULL) {
|
||||
printer->Print(vars,
|
||||
"$classname$_descriptor_ = file->enum_type($index$);\n");
|
||||
"file_level_enum_descriptors[$index_in_metadata$] = "
|
||||
"file->enum_type($index$);\n");
|
||||
} else {
|
||||
vars["parent"] = ClassName(descriptor_->containing_type(), false);
|
||||
printer->Print(vars,
|
||||
"$classname$_descriptor_ = $parent$_descriptor_->enum_type($index$);\n");
|
||||
"file_level_enum_descriptors[$index_in_metadata$] = "
|
||||
"$parent$_descriptor->enum_type($index$);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void EnumGenerator::GenerateMethods(io::Printer* printer) {
|
||||
map<string, string> vars;
|
||||
std::map<string, string> vars;
|
||||
vars["classname"] = classname_;
|
||||
vars["index_in_metadata"] = SimpleItoa(index_in_metadata_);
|
||||
vars["constexpr"] = options_.proto_h ? "constexpr " : "";
|
||||
vars["file_namespace"] = FileLevelNamespace(descriptor_->file()->name());
|
||||
|
||||
if (HasDescriptorMethods(descriptor_->file())) {
|
||||
printer->Print(vars,
|
||||
"const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n"
|
||||
" protobuf_AssignDescriptorsOnce();\n"
|
||||
" return $classname$_descriptor_;\n"
|
||||
"}\n");
|
||||
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||
printer->Print(
|
||||
vars,
|
||||
"const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n"
|
||||
" $file_namespace$::protobuf_AssignDescriptorsOnce();\n"
|
||||
" return "
|
||||
"$file_namespace$::file_level_enum_descriptors[$index_in_metadata$];\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
printer->Print(vars,
|
||||
"bool $classname$_IsValid(int value) {\n"
|
||||
" switch(value) {\n");
|
||||
" switch (value) {\n");
|
||||
|
||||
// Multiple values may have the same number. Make sure we only cover
|
||||
// each number once by first constructing a set containing all valid
|
||||
// numbers, then printing a case statement for each element.
|
||||
|
||||
set<int> numbers;
|
||||
std::set<int> numbers;
|
||||
for (int j = 0; j < descriptor_->value_count(); j++) {
|
||||
const EnumValueDescriptor* value = descriptor_->value(j);
|
||||
numbers.insert(value->number());
|
||||
}
|
||||
|
||||
for (set<int>::iterator iter = numbers.begin();
|
||||
for (std::set<int>::iterator iter = numbers.begin();
|
||||
iter != numbers.end(); ++iter) {
|
||||
printer->Print(
|
||||
" case $number$:\n",
|
||||
"number", SimpleItoa(*iter));
|
||||
"number", Int32ToString(*iter));
|
||||
}
|
||||
|
||||
printer->Print(vars,
|
||||
@@ -232,23 +295,26 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) {
|
||||
if (descriptor_->containing_type() != NULL) {
|
||||
// We need to "define" the static constants which were declared in the
|
||||
// header, to give the linker a place to put them. Or at least the C++
|
||||
// standard says we have to. MSVC actually insists tha we do _not_ define
|
||||
// them again in the .cc file.
|
||||
printer->Print("#ifndef _MSC_VER\n");
|
||||
// standard says we have to. MSVC actually insists that we do _not_ define
|
||||
// them again in the .cc file, prior to VC++ 2015.
|
||||
printer->Print("#if !defined(_MSC_VER) || _MSC_VER >= 1900\n");
|
||||
|
||||
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");
|
||||
"$constexpr$const $classname$ $parent$::$value$;\n");
|
||||
}
|
||||
printer->Print(vars,
|
||||
"const $classname$ $parent$::$nested_name$_MIN;\n"
|
||||
"const $classname$ $parent$::$nested_name$_MAX;\n"
|
||||
"const int $parent$::$nested_name$_ARRAYSIZE;\n");
|
||||
"const $classname$ $parent$::$nested_name$_MAX;\n");
|
||||
if (generate_array_size_) {
|
||||
printer->Print(vars,
|
||||
"const int $parent$::$nested_name$_ARRAYSIZE;\n");
|
||||
}
|
||||
|
||||
printer->Print("#endif // _MSC_VER\n");
|
||||
printer->Print("#endif // !defined(_MSC_VER) || _MSC_VER >= 1900\n");
|
||||
}
|
||||
}
|
||||
|
||||
+21
-7
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -35,11 +35,12 @@
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
@@ -54,12 +55,20 @@ namespace cpp {
|
||||
class EnumGenerator {
|
||||
public:
|
||||
// See generator.cc for the meaning of dllexport_decl.
|
||||
explicit EnumGenerator(const EnumDescriptor* descriptor,
|
||||
const Options& options);
|
||||
EnumGenerator(const EnumDescriptor* descriptor, const Options& options);
|
||||
~EnumGenerator();
|
||||
|
||||
// Header stuff.
|
||||
|
||||
// Fills the name to use when declaring the enum. This is for use when
|
||||
// generating other .proto.h files. This code should be placed within the
|
||||
// enum's package namespace, but NOT within any class, even for nested
|
||||
// enums. A given key in enum_names will map from an enum class name to the
|
||||
// EnumDescriptor that was responsible for its inclusion in the map. This can
|
||||
// be used to associate the descriptor with the code generated for it.
|
||||
void FillForwardDeclaration(
|
||||
std::map<string, const EnumDescriptor*>* enum_names);
|
||||
|
||||
// Generate header code defining the enum. This code should be placed
|
||||
// within the enum's package namespace, but NOT within any class, even for
|
||||
// nested enums.
|
||||
@@ -79,7 +88,7 @@ class EnumGenerator {
|
||||
|
||||
// Generate code that initializes the global variable storing the enum's
|
||||
// descriptor.
|
||||
void GenerateDescriptorInitializer(io::Printer* printer, int index);
|
||||
void GenerateDescriptorInitializer(io::Printer* printer);
|
||||
|
||||
// Generate non-inline methods related to the enum, such as IsValidValue().
|
||||
// Goes in the .cc file.
|
||||
@@ -87,9 +96,14 @@ class EnumGenerator {
|
||||
|
||||
private:
|
||||
const EnumDescriptor* descriptor_;
|
||||
string classname_;
|
||||
Options options_;
|
||||
const string classname_;
|
||||
const Options& options_;
|
||||
// whether to generate the *_ARRAYSIZE constant.
|
||||
const bool generate_array_size_;
|
||||
|
||||
int index_in_metadata_;
|
||||
|
||||
friend class FileGenerator;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
|
||||
};
|
||||
|
||||
+220
-71
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -35,7 +35,7 @@
|
||||
#include <google/protobuf/compiler/cpp/cpp_enum_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
@@ -46,22 +46,22 @@ namespace cpp {
|
||||
namespace {
|
||||
|
||||
void SetEnumVariables(const FieldDescriptor* descriptor,
|
||||
map<string, string>* variables,
|
||||
std::map<string, string>* variables,
|
||||
const Options& options) {
|
||||
SetCommonFieldVariables(descriptor, variables, options);
|
||||
const EnumValueDescriptor* default_value = descriptor->default_value_enum();
|
||||
(*variables)["type"] = ClassName(descriptor->enum_type(), true);
|
||||
(*variables)["default"] = SimpleItoa(default_value->number());
|
||||
(*variables)["default"] = Int32ToString(default_value->number());
|
||||
(*variables)["full_name"] = descriptor->full_name();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// ===================================================================
|
||||
|
||||
EnumFieldGenerator::
|
||||
EnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: descriptor_(descriptor) {
|
||||
EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: FieldGenerator(options), descriptor_(descriptor) {
|
||||
SetEnumVariables(descriptor, &variables_, options);
|
||||
}
|
||||
|
||||
@@ -75,20 +75,29 @@ 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");
|
||||
"$deprecated_attr$$type$ $name$() const;\n"
|
||||
"$deprecated_attr$void set_$name$($type$ value);\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 {
|
||||
std::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"
|
||||
" assert($type$_IsValid(value));\n"
|
||||
" set_has_$name$();\n"
|
||||
"$inline$void $classname$::set_$name$($type$ value) {\n");
|
||||
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
|
||||
printer->Print(variables,
|
||||
" assert($type$_IsValid(value));\n");
|
||||
}
|
||||
printer->Print(variables,
|
||||
" $set_hasbit$\n"
|
||||
" $name$_ = value;\n"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
@@ -112,22 +121,39 @@ GenerateConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_ = $default$;\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateCopyConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_ = from.$name$_;\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"int value;\n"
|
||||
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
|
||||
" int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
|
||||
" input, &value)));\n"
|
||||
"if ($type$_IsValid(value)) {\n"
|
||||
" set_$name$(static_cast< $type$ >(value));\n");
|
||||
if (HasUnknownFields(descriptor_->file())) {
|
||||
" input, &value)));\n");
|
||||
if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
|
||||
printer->Print(variables_,
|
||||
"} else {\n"
|
||||
" mutable_unknown_fields()->AddVarint($number$, value);\n");
|
||||
"set_$name$(static_cast< $type$ >(value));\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"if ($type$_IsValid(value)) {\n"
|
||||
" set_$name$(static_cast< $type$ >(value));\n");
|
||||
if (UseUnknownFieldSet(descriptor_->file(), options_)) {
|
||||
printer->Print(variables_,
|
||||
"} else {\n"
|
||||
" mutable_unknown_fields()->AddVarint($number$, value);\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
"} else {\n"
|
||||
" unknown_fields_stream.WriteVarint32($tag$u);\n"
|
||||
" unknown_fields_stream.WriteVarint32(value);\n",
|
||||
"tag", SimpleItoa(internal::WireFormat::MakeTag(descriptor_)));
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"}\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
@@ -153,10 +179,65 @@ GenerateByteSize(io::Printer* printer) const {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
RepeatedEnumFieldGenerator::
|
||||
RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: descriptor_(descriptor) {
|
||||
EnumOneofFieldGenerator::
|
||||
EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: EnumFieldGenerator(descriptor, options) {
|
||||
SetCommonOneofFieldVariables(descriptor, &variables_);
|
||||
}
|
||||
|
||||
EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {}
|
||||
|
||||
void EnumOneofFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer,
|
||||
bool is_inline) const {
|
||||
std::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");
|
||||
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
|
||||
printer->Print(variables,
|
||||
" assert($type$_IsValid(value));\n");
|
||||
}
|
||||
printer->Print(variables,
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" }\n"
|
||||
" $oneof_prefix$$name$_ = value;\n"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumOneofFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n");
|
||||
}
|
||||
|
||||
void EnumOneofFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
// Don't print any swapping code. Swapping the union will swap this field.
|
||||
}
|
||||
|
||||
void EnumOneofFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"_$classname$_default_instance_.$name$_ = $default$;\n");
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
|
||||
const FieldDescriptor* descriptor, const Options& options)
|
||||
: FieldGenerator(options), descriptor_(descriptor) {
|
||||
SetEnumVariables(descriptor, &variables_, options);
|
||||
}
|
||||
|
||||
@@ -166,7 +247,8 @@ void RepeatedEnumFieldGenerator::
|
||||
GeneratePrivateMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::RepeatedField<int> $name$_;\n");
|
||||
if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) {
|
||||
if (descriptor_->is_packed() &&
|
||||
HasGeneratedMethods(descriptor_->file(), options_)) {
|
||||
printer->Print(variables_,
|
||||
"mutable int _$name$_cached_byte_size_;\n");
|
||||
}
|
||||
@@ -175,35 +257,51 @@ 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");
|
||||
"$deprecated_attr$$type$ $name$(int index) const;\n"
|
||||
"$deprecated_attr$void set_$name$(int index, $type$ value);\n"
|
||||
"$deprecated_attr$void add_$name$($type$ value);\n");
|
||||
printer->Print(variables_,
|
||||
"inline const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n"
|
||||
"inline ::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n");
|
||||
"$deprecated_attr$const ::google::protobuf::RepeatedField<int>& $name$() const;\n"
|
||||
"$deprecated_attr$::google::protobuf::RepeatedField<int>* mutable_$name$();\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 {
|
||||
std::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"
|
||||
" assert($type$_IsValid(value));\n"
|
||||
"$inline$void $classname$::set_$name$(int index, $type$ value) {\n");
|
||||
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
|
||||
printer->Print(variables,
|
||||
" assert($type$_IsValid(value));\n");
|
||||
}
|
||||
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"
|
||||
" assert($type$_IsValid(value));\n"
|
||||
"$inline$void $classname$::add_$name$($type$ value) {\n");
|
||||
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
|
||||
printer->Print(variables,
|
||||
" assert($type$_IsValid(value));\n");
|
||||
}
|
||||
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"
|
||||
"}\n");
|
||||
}
|
||||
@@ -220,7 +318,7 @@ GenerateMergingCode(io::Printer* printer) const {
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
|
||||
printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
@@ -235,27 +333,59 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
"int value;\n"
|
||||
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
|
||||
" int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
|
||||
" input, &value)));\n"
|
||||
"if ($type$_IsValid(value)) {\n"
|
||||
" add_$name$(static_cast< $type$ >(value));\n");
|
||||
if (HasUnknownFields(descriptor_->file())) {
|
||||
" input, &value)));\n");
|
||||
if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
|
||||
printer->Print(variables_,
|
||||
"} else {\n"
|
||||
" mutable_unknown_fields()->AddVarint($number$, value);\n");
|
||||
"add_$name$(static_cast< $type$ >(value));\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"if ($type$_IsValid(value)) {\n"
|
||||
" add_$name$(static_cast< $type$ >(value));\n");
|
||||
if (UseUnknownFieldSet(descriptor_->file(), options_)) {
|
||||
printer->Print(variables_,
|
||||
"} else {\n"
|
||||
" mutable_unknown_fields()->AddVarint($number$, value);\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
"} else {\n"
|
||||
" unknown_fields_stream.WriteVarint32(tag);\n"
|
||||
" unknown_fields_stream.WriteVarint32(value);\n");
|
||||
}
|
||||
printer->Print("}\n");
|
||||
}
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
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"
|
||||
" &$type$_IsValid,\n"
|
||||
" this->mutable_$name$())));\n");
|
||||
if (!descriptor_->is_packed()) {
|
||||
// This path is rarely executed, so we use a non-inlined implementation.
|
||||
if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
|
||||
printer->Print(variables_,
|
||||
"DO_((::google::protobuf::internal::"
|
||||
"WireFormatLite::ReadPackedEnumPreserveUnknowns(\n"
|
||||
" input,\n"
|
||||
" $number$,\n"
|
||||
" NULL,\n"
|
||||
" NULL,\n"
|
||||
" this->mutable_$name$())));\n");
|
||||
} else if (UseUnknownFieldSet(descriptor_->file(), options_)) {
|
||||
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_,
|
||||
"DO_((::google::protobuf::internal::"
|
||||
"WireFormatLite::ReadPackedEnumPreserveUnknowns(\n"
|
||||
" input,\n"
|
||||
" $number$,\n"
|
||||
" $type$_IsValid,\n"
|
||||
" &unknown_fields_stream,\n"
|
||||
" this->mutable_$name$())));\n");
|
||||
}
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::uint32 length;\n"
|
||||
@@ -266,10 +396,27 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
|
||||
" int value;\n"
|
||||
" DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
|
||||
" int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
|
||||
" input, &value)));\n"
|
||||
" input, &value)));\n");
|
||||
if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
|
||||
printer->Print(variables_,
|
||||
" add_$name$(static_cast< $type$ >(value));\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" if ($type$_IsValid(value)) {\n"
|
||||
" add_$name$(static_cast< $type$ >(value));\n"
|
||||
" }\n"
|
||||
" } else {\n");
|
||||
if (UseUnknownFieldSet(descriptor_->file(), options_)) {
|
||||
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_,
|
||||
"}\n"
|
||||
"input->PopLimit(limit);\n");
|
||||
}
|
||||
@@ -277,7 +424,7 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
if (descriptor_->options().packed()) {
|
||||
if (descriptor_->is_packed()) {
|
||||
// Write the tag and the size.
|
||||
printer->Print(variables_,
|
||||
"if (this->$name$_size() > 0) {\n"
|
||||
@@ -290,7 +437,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||
if (descriptor_->options().packed()) {
|
||||
if (descriptor_->is_packed()) {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormatLite::WriteEnumNoTag(\n"
|
||||
" this->$name$(i), output);\n");
|
||||
@@ -304,7 +451,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
if (descriptor_->options().packed()) {
|
||||
if (descriptor_->is_packed()) {
|
||||
// Write the tag and the size.
|
||||
printer->Print(variables_,
|
||||
"if (this->$name$_size() > 0) {\n"
|
||||
@@ -318,7 +465,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||
if (descriptor_->options().packed()) {
|
||||
if (descriptor_->is_packed()) {
|
||||
printer->Print(variables_,
|
||||
" target = ::google::protobuf::internal::WireFormatLite::WriteEnumNoTagToArray(\n"
|
||||
" this->$name$(i), target);\n");
|
||||
@@ -334,27 +481,29 @@ void RepeatedEnumFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"{\n"
|
||||
" int data_size = 0;\n");
|
||||
" size_t data_size = 0;\n"
|
||||
" unsigned int count = this->$name$_size();");
|
||||
printer->Indent();
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||
"for (unsigned int i = 0; i < count; i++) {\n"
|
||||
" data_size += ::google::protobuf::internal::WireFormatLite::EnumSize(\n"
|
||||
" this->$name$(i));\n"
|
||||
"}\n");
|
||||
|
||||
if (descriptor_->options().packed()) {
|
||||
if (descriptor_->is_packed()) {
|
||||
printer->Print(variables_,
|
||||
"if (data_size > 0) {\n"
|
||||
" total_size += $tag_size$ +\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
|
||||
"}\n"
|
||||
"int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);\n"
|
||||
"GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
|
||||
"_$name$_cached_byte_size_ = data_size;\n"
|
||||
"_$name$_cached_byte_size_ = cached_size;\n"
|
||||
"GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
|
||||
"total_size += data_size;\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ * this->$name$_size() + data_size;\n");
|
||||
"total_size += ($tag_size$UL * count) + data_size;\n");
|
||||
}
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
+31
-10
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -46,44 +46,65 @@ namespace cpp {
|
||||
|
||||
class EnumFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
explicit EnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
|
||||
~EnumFieldGenerator();
|
||||
|
||||
// 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;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
protected:
|
||||
const FieldDescriptor* descriptor_;
|
||||
map<string, string> variables_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
|
||||
};
|
||||
|
||||
class EnumOneofFieldGenerator : public EnumFieldGenerator {
|
||||
public:
|
||||
EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~EnumOneofFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
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;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator);
|
||||
};
|
||||
|
||||
class RepeatedEnumFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~RepeatedEnumFieldGenerator();
|
||||
|
||||
// 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;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const {}
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||
@@ -92,7 +113,7 @@ class RepeatedEnumFieldGenerator : public FieldGenerator {
|
||||
|
||||
private:
|
||||
const FieldDescriptor* descriptor_;
|
||||
map<string, string> variables_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
|
||||
};
|
||||
+21
-19
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -92,7 +92,7 @@ ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
|
||||
ExtensionGenerator::~ExtensionGenerator() {}
|
||||
|
||||
void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
|
||||
map<string, string> vars;
|
||||
std::map<string, string> vars;
|
||||
vars["extendee" ] = ExtendeeClassName(descriptor_);
|
||||
vars["number" ] = SimpleItoa(descriptor_->number());
|
||||
vars["type_traits" ] = type_traits_;
|
||||
@@ -128,7 +128,7 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
|
||||
ClassName(descriptor_->extension_scope(), false) + "::";
|
||||
string name = scope + descriptor_->name();
|
||||
|
||||
map<string, string> vars;
|
||||
std::map<string, string> vars;
|
||||
vars["extendee" ] = ExtendeeClassName(descriptor_);
|
||||
vars["type_traits" ] = type_traits_;
|
||||
vars["name" ] = name;
|
||||
@@ -155,7 +155,7 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
|
||||
// Likewise, class members need to declare the field constant variable.
|
||||
if (descriptor_->extension_scope() != NULL) {
|
||||
printer->Print(vars,
|
||||
"#ifndef _MSC_VER\n"
|
||||
"#if !defined(_MSC_VER) || _MSC_VER >= 1900\n"
|
||||
"const int $scope$$constant_name$;\n"
|
||||
"#endif\n");
|
||||
}
|
||||
@@ -167,7 +167,7 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
|
||||
}
|
||||
|
||||
void ExtensionGenerator::GenerateRegistration(io::Printer* printer) {
|
||||
map<string, string> vars;
|
||||
std::map<string, string> vars;
|
||||
vars["extendee" ] = ExtendeeClassName(descriptor_);
|
||||
vars["number" ] = SimpleItoa(descriptor_->number());
|
||||
vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
|
||||
@@ -178,28 +178,30 @@ void ExtensionGenerator::GenerateRegistration(io::Printer* printer) {
|
||||
|
||||
switch (descriptor_->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
printer->Print(vars,
|
||||
"::google::protobuf::internal::ExtensionSet::RegisterEnumExtension(\n"
|
||||
" &$extendee$::default_instance(),\n"
|
||||
" $number$, $field_type$, $is_repeated$, $is_packed$,\n");
|
||||
printer->Print(
|
||||
vars,
|
||||
"::google::protobuf::internal::ExtensionSet::RegisterEnumExtension(\n"
|
||||
" $extendee$::internal_default_instance(),\n"
|
||||
" $number$, $field_type$, $is_repeated$, $is_packed$,\n");
|
||||
printer->Print(
|
||||
" &$type$_IsValid);\n",
|
||||
"type", ClassName(descriptor_->enum_type(), true));
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
printer->Print(vars,
|
||||
"::google::protobuf::internal::ExtensionSet::RegisterMessageExtension(\n"
|
||||
" &$extendee$::default_instance(),\n"
|
||||
" $number$, $field_type$, $is_repeated$, $is_packed$,\n");
|
||||
printer->Print(
|
||||
" &$type$::default_instance());\n",
|
||||
"type", ClassName(descriptor_->message_type(), true));
|
||||
vars,
|
||||
"::google::protobuf::internal::ExtensionSet::RegisterMessageExtension(\n"
|
||||
" $extendee$::internal_default_instance(),\n"
|
||||
" $number$, $field_type$, $is_repeated$, $is_packed$,\n");
|
||||
printer->Print(" $type$::internal_default_instance());\n", "type",
|
||||
ClassName(descriptor_->message_type(), true));
|
||||
break;
|
||||
default:
|
||||
printer->Print(vars,
|
||||
"::google::protobuf::internal::ExtensionSet::RegisterExtension(\n"
|
||||
" &$extendee$::default_instance(),\n"
|
||||
" $number$, $field_type$, $is_repeated$, $is_packed$);\n");
|
||||
printer->Print(
|
||||
vars,
|
||||
"::google::protobuf::internal::ExtensionSet::RegisterExtension(\n"
|
||||
" $extendee$::internal_default_instance(),\n"
|
||||
" $number$, $field_type$, $is_repeated$, $is_packed$);\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -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();
|
||||
|
||||
+64
-5
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -33,14 +33,21 @@
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||
#include <memory>
|
||||
#ifndef _SHARED_PTR_H
|
||||
#include <google/protobuf/stubs/shared_ptr.h>
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_string_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_enum_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_map_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_message_field.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
@@ -52,7 +59,7 @@ namespace cpp {
|
||||
using internal::WireFormat;
|
||||
|
||||
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
||||
map<string, string>* variables,
|
||||
std::map<string, string>* variables,
|
||||
const Options& options) {
|
||||
(*variables)["name"] = FieldName(descriptor);
|
||||
(*variables)["index"] = SimpleItoa(descriptor->index());
|
||||
@@ -60,12 +67,43 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
||||
(*variables)["classname"] = ClassName(FieldScope(descriptor), false);
|
||||
(*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
|
||||
|
||||
// non_null_ptr_to_name is usable only if has_$name$ is true. It yields a
|
||||
// pointer that will not be NULL. Subclasses of FieldGenerator may set
|
||||
// (*variables)["non_null_ptr_to_name"] differently.
|
||||
(*variables)["non_null_ptr_to_name"] =
|
||||
StrCat("&this->", FieldName(descriptor), "()");
|
||||
|
||||
(*variables)["tag_size"] = SimpleItoa(
|
||||
WireFormat::TagSize(descriptor->number(), descriptor->type()));
|
||||
(*variables)["deprecation"] = descriptor->options().deprecated()
|
||||
? " PROTOBUF_DEPRECATED" : "";
|
||||
(*variables)["deprecated_attr"] = descriptor->options().deprecated()
|
||||
? "GOOGLE_PROTOBUF_DEPRECATED_ATTR " : "";
|
||||
|
||||
(*variables)["cppget"] = "Get";
|
||||
|
||||
if (HasFieldPresence(descriptor->file())) {
|
||||
(*variables)["set_hasbit"] =
|
||||
"set_has_" + FieldName(descriptor) + "();";
|
||||
(*variables)["clear_hasbit"] =
|
||||
"clear_has_" + FieldName(descriptor) + "();";
|
||||
} else {
|
||||
(*variables)["set_hasbit"] = "";
|
||||
(*variables)["clear_hasbit"] = "";
|
||||
}
|
||||
|
||||
// By default, empty string, so that generic code used for both oneofs and
|
||||
// singular fields can be written.
|
||||
(*variables)["oneof_prefix"] = "";
|
||||
}
|
||||
|
||||
void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
|
||||
std::map<string, string>* variables) {
|
||||
const string prefix = descriptor->containing_oneof()->name() + "_.";
|
||||
(*variables)["oneof_prefix"] = prefix;
|
||||
(*variables)["oneof_name"] = descriptor->containing_oneof()->name();
|
||||
(*variables)["non_null_ptr_to_name"] =
|
||||
StrCat(prefix, (*variables)["name"], "_");
|
||||
}
|
||||
|
||||
FieldGenerator::~FieldGenerator() {}
|
||||
@@ -84,8 +122,10 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
|
||||
|
||||
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
|
||||
const Options& options)
|
||||
: descriptor_(descriptor),
|
||||
field_generators_(new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
|
||||
: descriptor_(descriptor),
|
||||
options_(options),
|
||||
field_generators_(
|
||||
new google::protobuf::scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
|
||||
// Construct all the FieldGenerators.
|
||||
for (int i = 0; i < descriptor->field_count(); i++) {
|
||||
field_generators_[i].reset(MakeGenerator(descriptor->field(i), options));
|
||||
@@ -97,7 +137,11 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
|
||||
if (field->is_repeated()) {
|
||||
switch (field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
return new RepeatedMessageFieldGenerator(field, options);
|
||||
if (field->is_map()) {
|
||||
return new MapFieldGenerator(field, options);
|
||||
} else {
|
||||
return new RepeatedMessageFieldGenerator(field, options);
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
switch (field->options().ctype()) {
|
||||
default: // RepeatedStringFieldGenerator handles unknown ctypes.
|
||||
@@ -109,6 +153,21 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
|
||||
default:
|
||||
return new RepeatedPrimitiveFieldGenerator(field, options);
|
||||
}
|
||||
} else if (field->containing_oneof()) {
|
||||
switch (field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
return new MessageOneofFieldGenerator(field, options);
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
switch (field->options().ctype()) {
|
||||
default: // StringOneofFieldGenerator handles unknown ctypes.
|
||||
case FieldOptions::STRING:
|
||||
return new StringOneofFieldGenerator(field, options);
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
return new EnumOneofFieldGenerator(field, options);
|
||||
default:
|
||||
return new PrimitiveOneofFieldGenerator(field, options);
|
||||
}
|
||||
} else {
|
||||
switch (field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
+78
-13
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -36,9 +36,12 @@
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#ifndef _SHARED_PTR_H
|
||||
#include <google/protobuf/stubs/shared_ptr.h>
|
||||
#endif
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||
|
||||
@@ -58,12 +61,15 @@ namespace cpp {
|
||||
// ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size',
|
||||
// 'deprecation'].
|
||||
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
||||
map<string, string>* variables,
|
||||
std::map<string, string>* variables,
|
||||
const Options& options);
|
||||
|
||||
void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
|
||||
std::map<string, string>* variables);
|
||||
|
||||
class FieldGenerator {
|
||||
public:
|
||||
FieldGenerator() {}
|
||||
explicit FieldGenerator(const Options& options) : options_(options) {}
|
||||
virtual ~FieldGenerator();
|
||||
|
||||
// Generate lines of code declaring members fields of the message class
|
||||
@@ -71,26 +77,67 @@ class FieldGenerator {
|
||||
// class.
|
||||
virtual void GeneratePrivateMembers(io::Printer* printer) const = 0;
|
||||
|
||||
// Generate static default variable for this field. These are placed inside
|
||||
// the message class. Most field types don't need this, so the default
|
||||
// implementation is empty.
|
||||
virtual void GenerateStaticMembers(io::Printer* /*printer*/) const {}
|
||||
|
||||
// Generate prototypes for accessors that will manipulate imported
|
||||
// messages inline. These are for .proto.h headers.
|
||||
//
|
||||
// In .proto.h mode, the headers of imports are not #included. However,
|
||||
// functions that manipulate the imported message types need access to
|
||||
// the class definition of the imported message, meaning that the headers
|
||||
// must be #included. To get around this, functions that manipulate
|
||||
// imported message objects are defined as dependent functions in a base
|
||||
// template class. By making them dependent template functions, the
|
||||
// function templates will not be instantiated until they are called, so
|
||||
// we can defer to those translation units to #include the necessary
|
||||
// generated headers.
|
||||
//
|
||||
// See:
|
||||
// http://en.cppreference.com/w/cpp/language/class_template#Implicit_instantiation
|
||||
//
|
||||
// Most field types don't need this, so the default implementation is empty.
|
||||
virtual void GenerateDependentAccessorDeclarations(
|
||||
io::Printer* printer) const {}
|
||||
|
||||
// Generate prototypes for all of the accessor functions related to this
|
||||
// field. These are placed inside the class definition.
|
||||
virtual void GenerateAccessorDeclarations(io::Printer* printer) const = 0;
|
||||
|
||||
// Generate inline definitions of depenent accessor functions for this field.
|
||||
// These are placed inside the header after all class definitions.
|
||||
virtual void GenerateDependentInlineAccessorDefinitions(
|
||||
io::Printer* printer) const {}
|
||||
|
||||
// Generate inline definitions of accessor functions for this field.
|
||||
// These are placed inside the header after all class definitions.
|
||||
// In non-.proto.h mode, this generates dependent accessor functions as well.
|
||||
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.
|
||||
// Most field types don't need this, so the default implementation is empty.
|
||||
virtual void GenerateNonInlineAccessorDefinitions(
|
||||
io::Printer* printer) const {}
|
||||
io::Printer* /*printer*/) const {}
|
||||
|
||||
// Generate lines of code (statements, not declarations) which clear the
|
||||
// field. This is used to define the clear_$name$() method as well as
|
||||
// the Clear() method for the whole message.
|
||||
// field. This is used to define the clear_$name$() method
|
||||
virtual void GenerateClearingCode(io::Printer* printer) const = 0;
|
||||
|
||||
// Generate lines of code (statements, not declarations) which clear the field
|
||||
// as part of the Clear() method for the whole message. For message types
|
||||
// which have field presence bits, MessageGenerator::GenerateClear will have
|
||||
// already checked the presence bits.
|
||||
//
|
||||
// Since most field types can re-use GenerateClearingCode, this method is not
|
||||
// pure virtual.
|
||||
virtual void GenerateMessageClearingCode(io::Printer* printer) const {
|
||||
GenerateClearingCode(printer);
|
||||
}
|
||||
|
||||
// Generate lines of code (statements, not declarations) which merges the
|
||||
// contents of the field from the current message to the target message,
|
||||
// which is stored in the generated code variable "from".
|
||||
@@ -99,6 +146,9 @@ class FieldGenerator {
|
||||
// GenerateMergeFrom method.
|
||||
virtual void GenerateMergingCode(io::Printer* printer) const = 0;
|
||||
|
||||
// Generates a copy constructor
|
||||
virtual void GenerateCopyConstructorCode(io::Printer* printer) const = 0;
|
||||
|
||||
// Generate lines of code (statements, not declarations) which swaps
|
||||
// this field and the corresponding field of another message, which
|
||||
// is stored in the generated code variable "other". This is used to
|
||||
@@ -114,14 +164,25 @@ class FieldGenerator {
|
||||
// Generate any code that needs to go in the class's SharedDtor() method,
|
||||
// invoked by the destructor.
|
||||
// Most field types don't need this, so the default implementation is empty.
|
||||
virtual void GenerateDestructorCode(io::Printer* printer) const {}
|
||||
virtual void GenerateDestructorCode(io::Printer* /*printer*/) const {}
|
||||
|
||||
// Generate a manual destructor invocation for use when the message is on an
|
||||
// arena. The code that this method generates will be executed inside a
|
||||
// shared-for-the-whole-message-class method registered with OwnDestructor().
|
||||
// The method should return |true| if it generated any code that requires a
|
||||
// call; this allows the message generator to eliminate the OwnDestructor()
|
||||
// registration if no fields require it.
|
||||
virtual bool GenerateArenaDestructorCode(io::Printer* printer) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate code that allocates the fields's default instance.
|
||||
virtual void GenerateDefaultInstanceAllocator(io::Printer* printer) const {}
|
||||
virtual void GenerateDefaultInstanceAllocator(io::Printer* /*printer*/)
|
||||
const {}
|
||||
|
||||
// Generate code that should be run when ShutdownProtobufLibrary() is called,
|
||||
// to delete all dynamically-allocated objects.
|
||||
virtual void GenerateShutdownCode(io::Printer* printer) const {}
|
||||
virtual void GenerateShutdownCode(io::Printer* /*printer*/) const {}
|
||||
|
||||
// Generate lines to decode this field, which will be placed inside the
|
||||
// message's MergeFromCodedStream() method.
|
||||
@@ -146,6 +207,9 @@ class FieldGenerator {
|
||||
// are placed in the message's ByteSize() method.
|
||||
virtual void GenerateByteSize(io::Printer* printer) const = 0;
|
||||
|
||||
protected:
|
||||
const Options& options_;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
|
||||
};
|
||||
@@ -153,14 +217,15 @@ class FieldGenerator {
|
||||
// Convenience class which constructs FieldGenerators for a Descriptor.
|
||||
class FieldGeneratorMap {
|
||||
public:
|
||||
explicit FieldGeneratorMap(const Descriptor* descriptor, const Options& options);
|
||||
FieldGeneratorMap(const Descriptor* descriptor, const Options& options);
|
||||
~FieldGeneratorMap();
|
||||
|
||||
const FieldGenerator& get(const FieldDescriptor* field) const;
|
||||
|
||||
private:
|
||||
const Descriptor* descriptor_;
|
||||
scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
|
||||
const Options& options_;
|
||||
google::protobuf::scoped_array<google::protobuf::scoped_ptr<FieldGenerator> > field_generators_;
|
||||
|
||||
static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
|
||||
const Options& options);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,167 @@
|
||||
// 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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
|
||||
|
||||
#include <memory>
|
||||
#ifndef _SHARED_PTR_H
|
||||
#include <google/protobuf/stubs/shared_ptr.h>
|
||||
#endif
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class FileDescriptor; // descriptor.h
|
||||
namespace io {
|
||||
class Printer; // printer.h
|
||||
}
|
||||
}
|
||||
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
class EnumGenerator; // enum.h
|
||||
class MessageGenerator; // message.h
|
||||
class ServiceGenerator; // service.h
|
||||
class ExtensionGenerator; // extension.h
|
||||
|
||||
class FileGenerator {
|
||||
public:
|
||||
// See generator.cc for the meaning of dllexport_decl.
|
||||
FileGenerator(const FileDescriptor* file, const Options& options);
|
||||
~FileGenerator();
|
||||
|
||||
// Shared code between the two header generators below.
|
||||
void GenerateHeader(io::Printer* printer);
|
||||
|
||||
// info_path, if non-empty, should be the path (relative to printer's output)
|
||||
// to the metadata file describing this proto header.
|
||||
void GenerateProtoHeader(io::Printer* printer,
|
||||
const string& info_path);
|
||||
// info_path, if non-empty, should be the path (relative to printer's output)
|
||||
// to the metadata file describing this PB header.
|
||||
void GeneratePBHeader(io::Printer* printer,
|
||||
const string& info_path);
|
||||
void GenerateSource(io::Printer* printer);
|
||||
|
||||
private:
|
||||
// Internal type used by GenerateForwardDeclarations (defined in file.cc).
|
||||
class ForwardDeclarations;
|
||||
|
||||
// Generate the BuildDescriptors() procedure, which builds all descriptors
|
||||
// for types defined in the file.
|
||||
void GenerateBuildDescriptors(io::Printer* printer);
|
||||
|
||||
void GenerateNamespaceOpeners(io::Printer* printer);
|
||||
void GenerateNamespaceClosers(io::Printer* printer);
|
||||
|
||||
// For other imports, generates their forward-declarations.
|
||||
void GenerateForwardDeclarations(io::Printer* printer);
|
||||
|
||||
// Internal helper used by GenerateForwardDeclarations: fills 'decls'
|
||||
// with all necessary forward-declarations for this file and its
|
||||
// transient depednencies.
|
||||
void FillForwardDeclarations(ForwardDeclarations* decls);
|
||||
|
||||
// Generates top or bottom of a header file.
|
||||
void GenerateTopHeaderGuard(io::Printer* printer,
|
||||
const string& filename_identifier);
|
||||
void GenerateBottomHeaderGuard(io::Printer* printer,
|
||||
const string& filename_identifier);
|
||||
|
||||
// Generates #include directives.
|
||||
void GenerateLibraryIncludes(io::Printer* printer);
|
||||
void GenerateDependencyIncludes(io::Printer* printer);
|
||||
|
||||
// Generate a pragma to pull in metadata using the given info_path (if
|
||||
// non-empty). info_path should be relative to printer's output.
|
||||
void GenerateMetadataPragma(io::Printer* printer, const string& info_path);
|
||||
|
||||
// Generates a couple of different pieces before definitions:
|
||||
void GenerateGlobalStateFunctionDeclarations(io::Printer* printer);
|
||||
|
||||
// Generates types for classes.
|
||||
void GenerateMessageDefinitions(io::Printer* printer);
|
||||
|
||||
void GenerateEnumDefinitions(io::Printer* printer);
|
||||
|
||||
// Generates generic service definitions.
|
||||
void GenerateServiceDefinitions(io::Printer* printer);
|
||||
|
||||
// Generates extension identifiers.
|
||||
void GenerateExtensionIdentifiers(io::Printer* printer);
|
||||
|
||||
// Generates inline function defintions.
|
||||
void GenerateInlineFunctionDefinitions(io::Printer* printer);
|
||||
|
||||
void GenerateProto2NamespaceEnumSpecializations(io::Printer* printer);
|
||||
|
||||
const FileDescriptor* file_;
|
||||
const Options options_;
|
||||
|
||||
// Contains the post-order walk of all the messages (and child messages) in
|
||||
// this file. If you need a pre-order walk just reverse iterate.
|
||||
std::vector<MessageGenerator*> message_generators_;
|
||||
std::vector<EnumGenerator*> enum_generators_;
|
||||
std::vector<ServiceGenerator*> service_generators_;
|
||||
std::vector<ExtensionGenerator*> extension_generators_;
|
||||
|
||||
// These members are just for owning (and thus proper deleting). Some of the
|
||||
// message_ and enum_generators above are owned by child messages.
|
||||
google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> >
|
||||
message_generators_owner_;
|
||||
google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_owner_;
|
||||
google::protobuf::scoped_array<google::protobuf::scoped_ptr<ServiceGenerator> >
|
||||
service_generators_owner_;
|
||||
google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> >
|
||||
extension_generators_owner_;
|
||||
|
||||
// E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}.
|
||||
std::vector<string> package_parts_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
|
||||
+54
-10
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -35,6 +35,10 @@
|
||||
#include <google/protobuf/compiler/cpp/cpp_generator.h>
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#ifndef _SHARED_PTR_H
|
||||
#include <google/protobuf/stubs/shared_ptr.h>
|
||||
#endif
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_file.h>
|
||||
@@ -55,7 +59,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
|
||||
const string& parameter,
|
||||
GeneratorContext* generator_context,
|
||||
string* error) const {
|
||||
vector<pair<string, string> > options;
|
||||
std::vector<std::pair<string, string> > options;
|
||||
ParseGeneratorParameter(parameter, &options);
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
@@ -78,6 +82,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
|
||||
// }
|
||||
// FOO_EXPORT is a macro which should expand to __declspec(dllexport) or
|
||||
// __declspec(dllimport) depending on what is being compiled.
|
||||
//
|
||||
Options file_options;
|
||||
|
||||
for (int i = 0; i < options.size(); i++) {
|
||||
@@ -85,6 +90,14 @@ bool CppGenerator::Generate(const FileDescriptor* file,
|
||||
file_options.dllexport_decl = options[i].second;
|
||||
} else if (options[i].first == "safe_boundary_check") {
|
||||
file_options.safe_boundary_check = true;
|
||||
} else if (options[i].first == "annotate_headers") {
|
||||
file_options.annotate_headers = true;
|
||||
} else if (options[i].first == "annotation_pragma_name") {
|
||||
file_options.annotation_pragma_name = options[i].second;
|
||||
} else if (options[i].first == "annotation_guard_name") {
|
||||
file_options.annotation_guard_name = options[i].second;
|
||||
} else if (options[i].first == "lite") {
|
||||
file_options.enforce_lite = true;
|
||||
} else {
|
||||
*error = "Unknown generator option: " + options[i].first;
|
||||
return false;
|
||||
@@ -95,22 +108,53 @@ bool CppGenerator::Generate(const FileDescriptor* file,
|
||||
|
||||
|
||||
string basename = StripProto(file->name());
|
||||
basename.append(".pb");
|
||||
|
||||
FileGenerator file_generator(file, file_options);
|
||||
|
||||
// Generate header.
|
||||
// Generate header(s).
|
||||
if (file_options.proto_h) {
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
generator_context->Open(basename + ".proto.h"));
|
||||
GeneratedCodeInfo annotations;
|
||||
io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
|
||||
&annotations);
|
||||
string info_path = basename + ".proto.h.meta";
|
||||
io::Printer printer(output.get(), '$', file_options.annotate_headers
|
||||
? &annotation_collector
|
||||
: NULL);
|
||||
file_generator.GenerateProtoHeader(
|
||||
&printer, file_options.annotate_headers ? info_path : "");
|
||||
if (file_options.annotate_headers) {
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> info_output(
|
||||
generator_context->Open(info_path));
|
||||
annotations.SerializeToZeroCopyStream(info_output.get());
|
||||
}
|
||||
}
|
||||
|
||||
basename.append(".pb");
|
||||
{
|
||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
generator_context->Open(basename + ".h"));
|
||||
io::Printer printer(output.get(), '$');
|
||||
file_generator.GenerateHeader(&printer);
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
generator_context->Open(basename + ".h"));
|
||||
GeneratedCodeInfo annotations;
|
||||
io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
|
||||
&annotations);
|
||||
string info_path = basename + ".h.meta";
|
||||
io::Printer printer(output.get(), '$', file_options.annotate_headers
|
||||
? &annotation_collector
|
||||
: NULL);
|
||||
file_generator.GeneratePBHeader(
|
||||
&printer, file_options.annotate_headers ? info_path : "");
|
||||
if (file_options.annotate_headers) {
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> info_output(
|
||||
generator_context->Open(info_path));
|
||||
annotations.SerializeToZeroCopyStream(info_output.get());
|
||||
}
|
||||
}
|
||||
|
||||
// Generate cc file.
|
||||
{
|
||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
generator_context->Open(basename + ".cc"));
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
generator_context->Open(basename + ".cc"));
|
||||
io::Printer printer(output.get(), '$');
|
||||
file_generator.GenerateSource(&printer);
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
+313
-91
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/stubs/substitute.h>
|
||||
@@ -51,6 +52,10 @@ namespace cpp {
|
||||
|
||||
namespace {
|
||||
|
||||
static const char kAnyMessageName[] = "Any";
|
||||
static const char kAnyProtoFile[] = "google/protobuf/any.proto";
|
||||
static const char kGoogleProtobufPrefix[] = "google/protobuf/";
|
||||
|
||||
string DotsToUnderscores(const string& name) {
|
||||
return StringReplace(name, ".", "_", true);
|
||||
}
|
||||
@@ -60,16 +65,18 @@ string DotsToColons(const string& name) {
|
||||
}
|
||||
|
||||
const char* const kKeywordList[] = {
|
||||
"and", "and_eq", "asm", "auto", "bitand", "bitor", "bool", "break", "case",
|
||||
"catch", "char", "class", "compl", "const", "const_cast", "continue",
|
||||
"default", "delete", "do", "double", "dynamic_cast", "else", "enum",
|
||||
"explicit", "extern", "false", "float", "for", "friend", "goto", "if",
|
||||
"inline", "int", "long", "mutable", "namespace", "new", "not", "not_eq",
|
||||
"alignas", "alignof", "and", "and_eq", "asm", "auto", "bitand", "bitor",
|
||||
"bool", "break", "case", "catch", "char", "class", "compl", "const",
|
||||
"constexpr", "const_cast", "continue", "decltype", "default", "delete", "do",
|
||||
"double", "dynamic_cast", "else", "enum", "explicit", "export", "extern",
|
||||
"false", "float", "for", "friend", "goto", "if", "inline", "int", "long",
|
||||
"mutable", "namespace", "new", "noexcept", "not", "not_eq", "NULL",
|
||||
"operator", "or", "or_eq", "private", "protected", "public", "register",
|
||||
"reinterpret_cast", "return", "short", "signed", "sizeof", "static",
|
||||
"static_cast", "struct", "switch", "template", "this", "throw", "true", "try",
|
||||
"typedef", "typeid", "typename", "union", "unsigned", "using", "virtual",
|
||||
"void", "volatile", "wchar_t", "while", "xor", "xor_eq"
|
||||
"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"
|
||||
};
|
||||
|
||||
hash_set<string> MakeKeywordsMap() {
|
||||
@@ -82,6 +89,22 @@ hash_set<string> MakeKeywordsMap() {
|
||||
|
||||
hash_set<string> kKeywords = MakeKeywordsMap();
|
||||
|
||||
// Returns whether the provided descriptor has an extension. This includes its
|
||||
// nested types.
|
||||
bool HasExtension(const Descriptor* descriptor) {
|
||||
if (descriptor->extension_count() > 0) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < descriptor->nested_type_count(); ++i) {
|
||||
if (HasExtension(descriptor->nested_type(i))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
string UnderscoresToCamelCase(const string& input, bool cap_next_letter) {
|
||||
string result;
|
||||
// Note: I distrust ctype.h due to locales.
|
||||
@@ -107,22 +130,6 @@ string UnderscoresToCamelCase(const string& input, bool cap_next_letter) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns whether the provided descriptor has an extension. This includes its
|
||||
// nested types.
|
||||
bool HasExtension(const Descriptor* descriptor) {
|
||||
if (descriptor->extension_count() > 0) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < descriptor->nested_type_count(); ++i) {
|
||||
if (HasExtension(descriptor->nested_type(i))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const char kThickSeparator[] =
|
||||
"// ===================================================================\n";
|
||||
const char kThinSeparator[] =
|
||||
@@ -161,9 +168,22 @@ string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) {
|
||||
}
|
||||
|
||||
|
||||
string SuperClassName(const Descriptor* descriptor) {
|
||||
return HasDescriptorMethods(descriptor->file()) ?
|
||||
"::google::protobuf::Message" : "::google::protobuf::MessageLite";
|
||||
string DependentBaseClassTemplateName(const Descriptor* descriptor) {
|
||||
return ClassName(descriptor, false) + "_InternalBase";
|
||||
}
|
||||
|
||||
string SuperClassName(const Descriptor* descriptor, const Options& options) {
|
||||
return HasDescriptorMethods(descriptor->file(), options)
|
||||
? "::google::protobuf::Message"
|
||||
: "::google::protobuf::MessageLite";
|
||||
}
|
||||
|
||||
string DependentBaseDownCast() {
|
||||
return "reinterpret_cast<T*>(this)->";
|
||||
}
|
||||
|
||||
string DependentBaseConstDownCast() {
|
||||
return "reinterpret_cast<const T*>(this)->";
|
||||
}
|
||||
|
||||
string FieldName(const FieldDescriptor* field) {
|
||||
@@ -175,6 +195,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";
|
||||
@@ -191,6 +219,60 @@ string FieldConstantName(const FieldDescriptor *field) {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool IsFieldDependent(const FieldDescriptor* field) {
|
||||
if (field->containing_oneof() != NULL &&
|
||||
field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
|
||||
return true;
|
||||
}
|
||||
if (field->is_map()) {
|
||||
const Descriptor* map_descriptor = field->message_type();
|
||||
for (int i = 0; i < map_descriptor->field_count(); i++) {
|
||||
if (IsFieldDependent(map_descriptor->field(i))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
|
||||
return false;
|
||||
}
|
||||
if (field->containing_oneof() != NULL) {
|
||||
// Oneof fields will always be dependent.
|
||||
//
|
||||
// This is a unique case for field codegen. Field generators are
|
||||
// responsible for generating all the field-specific accessor
|
||||
// functions, except for the clear_*() function; instead, field
|
||||
// generators produce inline clearing code.
|
||||
//
|
||||
// For non-oneof fields, the Message class uses the inline clearing
|
||||
// code to define the field's clear_*() function, as well as in the
|
||||
// destructor. For oneof fields, the Message class generates a much
|
||||
// more complicated clear_*() function, which clears only the oneof
|
||||
// member that is set, in addition to clearing methods for each of the
|
||||
// oneof members individually.
|
||||
//
|
||||
// Since oneofs do not have their own generator class, the Message code
|
||||
// generation logic would be significantly complicated in order to
|
||||
// split dependent and non-dependent manipulation logic based on
|
||||
// whether the oneof truly needs to be dependent; so, for oneof fields,
|
||||
// we just assume it (and its constituents) should be manipulated by a
|
||||
// dependent base class function.
|
||||
//
|
||||
// This is less precise than how dependent message-typed fields are
|
||||
// handled, but the cost is limited to only the generated code for the
|
||||
// oneof field, which seems like an acceptable tradeoff.
|
||||
return true;
|
||||
}
|
||||
if (field->file() == field->message_type()->file()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
string DependentTypeName(const FieldDescriptor* field) {
|
||||
return "InternalBase_" + field->name() + "_T";
|
||||
}
|
||||
|
||||
string FieldMessageTypeName(const FieldDescriptor* field) {
|
||||
// Note: The Google-internal version of Protocol Buffers uses this function
|
||||
// as a hook point for hacks to support legacy code.
|
||||
@@ -256,34 +338,42 @@ const char* DeclaredTypeMethodName(FieldDescriptor::Type type) {
|
||||
return "";
|
||||
}
|
||||
|
||||
string Int32ToString(int number) {
|
||||
// gcc rejects the decimal form of kint32min.
|
||||
if (number == kint32min) {
|
||||
GOOGLE_COMPILE_ASSERT(kint32min == (~0x7fffffff), kint32min_value_error);
|
||||
return "(~0x7fffffff)";
|
||||
} else {
|
||||
return SimpleItoa(number);
|
||||
}
|
||||
}
|
||||
|
||||
string Int64ToString(int64 number) {
|
||||
// gcc rejects the decimal form of kint64min
|
||||
if (number == kint64min) {
|
||||
// Make sure we are in a 2's complement system.
|
||||
GOOGLE_COMPILE_ASSERT(kint64min == GOOGLE_LONGLONG(~0x7fffffffffffffff),
|
||||
kint64min_value_error);
|
||||
return "GOOGLE_LONGLONG(~0x7fffffffffffffff)";
|
||||
}
|
||||
return "GOOGLE_LONGLONG(" + SimpleItoa(number) + ")";
|
||||
}
|
||||
|
||||
string DefaultValue(const FieldDescriptor* field) {
|
||||
switch (field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_INT32:
|
||||
// gcc rejects the decimal form of kint32min and kint64min.
|
||||
if (field->default_value_int32() == kint32min) {
|
||||
// Make sure we are in a 2's complement system.
|
||||
GOOGLE_COMPILE_ASSERT(kint32min == -0x80000000, kint32min_value_error);
|
||||
return "-0x80000000";
|
||||
}
|
||||
return SimpleItoa(field->default_value_int32());
|
||||
return Int32ToString(field->default_value_int32());
|
||||
case FieldDescriptor::CPPTYPE_UINT32:
|
||||
return SimpleItoa(field->default_value_uint32()) + "u";
|
||||
case FieldDescriptor::CPPTYPE_INT64:
|
||||
// See the comments for CPPTYPE_INT32.
|
||||
if (field->default_value_int64() == kint64min) {
|
||||
// Make sure we are in a 2's complement system.
|
||||
GOOGLE_COMPILE_ASSERT(kint64min == GOOGLE_LONGLONG(-0x8000000000000000),
|
||||
kint64min_value_error);
|
||||
return "GOOGLE_LONGLONG(-0x8000000000000000)";
|
||||
}
|
||||
return "GOOGLE_LONGLONG(" + SimpleItoa(field->default_value_int64()) + ")";
|
||||
return Int64ToString(field->default_value_int64());
|
||||
case FieldDescriptor::CPPTYPE_UINT64:
|
||||
return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")";
|
||||
case FieldDescriptor::CPPTYPE_DOUBLE: {
|
||||
double value = field->default_value_double();
|
||||
if (value == numeric_limits<double>::infinity()) {
|
||||
if (value == std::numeric_limits<double>::infinity()) {
|
||||
return "::google::protobuf::internal::Infinity()";
|
||||
} else if (value == -numeric_limits<double>::infinity()) {
|
||||
} else if (value == -std::numeric_limits<double>::infinity()) {
|
||||
return "-::google::protobuf::internal::Infinity()";
|
||||
} else if (value != value) {
|
||||
return "::google::protobuf::internal::NaN()";
|
||||
@@ -294,9 +384,9 @@ string DefaultValue(const FieldDescriptor* field) {
|
||||
case FieldDescriptor::CPPTYPE_FLOAT:
|
||||
{
|
||||
float value = field->default_value_float();
|
||||
if (value == numeric_limits<float>::infinity()) {
|
||||
if (value == std::numeric_limits<float>::infinity()) {
|
||||
return "static_cast<float>(::google::protobuf::internal::Infinity())";
|
||||
} else if (value == -numeric_limits<float>::infinity()) {
|
||||
} else if (value == -std::numeric_limits<float>::infinity()) {
|
||||
return "static_cast<float>(-::google::protobuf::internal::Infinity())";
|
||||
} else if (value != value) {
|
||||
return "static_cast<float>(::google::protobuf::internal::NaN())";
|
||||
@@ -319,13 +409,14 @@ string DefaultValue(const FieldDescriptor* field) {
|
||||
return strings::Substitute(
|
||||
"static_cast< $0 >($1)",
|
||||
ClassName(field->enum_type(), true),
|
||||
field->default_value_enum()->number());
|
||||
Int32ToString(field->default_value_enum()->number()));
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
return "\"" + EscapeTrigraphs(
|
||||
CEscape(field->default_value_string())) +
|
||||
"\"";
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
return FieldMessageTypeName(field) + "::default_instance()";
|
||||
return "*" + FieldMessageTypeName(field) +
|
||||
"::internal_default_instance()";
|
||||
}
|
||||
// Can't actually get here; make compiler happy. (We could add a default
|
||||
// case above but then we wouldn't get the nice compiler warning when a
|
||||
@@ -343,27 +434,22 @@ 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, "_", strings::Hex(static_cast<uint8>(filename[i])));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Return the name of the AddDescriptors() function for a given file.
|
||||
string GlobalAddDescriptorsName(const string& filename) {
|
||||
return "protobuf_AddDesc_" + FilenameIdentifier(filename);
|
||||
string FileLevelNamespace(const string& filename) {
|
||||
return "protobuf_" + FilenameIdentifier(filename);
|
||||
}
|
||||
|
||||
// Return the name of the AssignDescriptors() function for a given file.
|
||||
string GlobalAssignDescriptorsName(const string& filename) {
|
||||
return "protobuf_AssignDesc_" + FilenameIdentifier(filename);
|
||||
}
|
||||
|
||||
// Return the name of the ShutdownFile() function for a given file.
|
||||
string GlobalShutdownFileName(const string& filename) {
|
||||
return "protobuf_ShutdownFile_" + FilenameIdentifier(filename);
|
||||
// Return the qualified C++ name for a file level symbol.
|
||||
string QualifiedFileLevelSymbol(const string& package, const string& name) {
|
||||
if (package.empty()) {
|
||||
return StrCat("::", name);
|
||||
}
|
||||
return StrCat("::", DotsToColons(package), "::", name);
|
||||
}
|
||||
|
||||
// Escape C++ trigraphs by escaping question marks to \?
|
||||
@@ -371,8 +457,29 @@ string EscapeTrigraphs(const string& to_escape) {
|
||||
return StringReplace(to_escape, "?", "\\?", true);
|
||||
}
|
||||
|
||||
bool StaticInitializersForced(const FileDescriptor* file) {
|
||||
if (HasDescriptorMethods(file) || file->extension_count() > 0) {
|
||||
// Escaped function name to eliminate naming conflict.
|
||||
string SafeFunctionName(const Descriptor* descriptor,
|
||||
const FieldDescriptor* field,
|
||||
const string& prefix) {
|
||||
// Do not use FieldName() since it will escape keywords.
|
||||
string name = field->name();
|
||||
LowerString(&name);
|
||||
string function_name = prefix + name;
|
||||
if (descriptor->FindFieldByName(function_name)) {
|
||||
// Single underscore will also make it conflicting with the private data
|
||||
// member. We use double underscore to escape function names.
|
||||
function_name.append("__");
|
||||
} else if (kKeywords.count(name) > 0) {
|
||||
// If the field name is a keyword, we append the underscore back to keep it
|
||||
// consistent with other function names.
|
||||
function_name.append("_");
|
||||
}
|
||||
return function_name;
|
||||
}
|
||||
|
||||
bool StaticInitializersForced(const FileDescriptor* file,
|
||||
const Options& options) {
|
||||
if (HasDescriptorMethods(file, options) || file->extension_count() > 0) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < file->message_type_count(); ++i) {
|
||||
@@ -383,39 +490,26 @@ bool StaticInitializersForced(const FileDescriptor* file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void PrintHandlingOptionalStaticInitializers(
|
||||
const FileDescriptor* file, io::Printer* printer,
|
||||
const char* with_static_init, const char* without_static_init,
|
||||
const char* var1, const string& val1,
|
||||
const char* var2, const string& val2) {
|
||||
map<string, string> vars;
|
||||
if (var1) {
|
||||
vars[var1] = val1;
|
||||
|
||||
static bool HasMapFields(const Descriptor* descriptor) {
|
||||
for (int i = 0; i < descriptor->field_count(); ++i) {
|
||||
if (descriptor->field(i)->is_map()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (var2) {
|
||||
vars[var2] = val2;
|
||||
for (int i = 0; i < descriptor->nested_type_count(); ++i) {
|
||||
if (HasMapFields(descriptor->nested_type(i))) return true;
|
||||
}
|
||||
PrintHandlingOptionalStaticInitializers(
|
||||
vars, file, printer, with_static_init, without_static_init);
|
||||
return false;
|
||||
}
|
||||
|
||||
void PrintHandlingOptionalStaticInitializers(
|
||||
const map<string, string>& vars, const FileDescriptor* file,
|
||||
io::Printer* printer, const char* with_static_init,
|
||||
const char* without_static_init) {
|
||||
if (StaticInitializersForced(file)) {
|
||||
printer->Print(vars, with_static_init);
|
||||
} else {
|
||||
printer->Print(vars, (string(
|
||||
"#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n") +
|
||||
without_static_init +
|
||||
"#else\n" +
|
||||
with_static_init +
|
||||
"#endif\n").c_str());
|
||||
bool HasMapFields(const FileDescriptor* file) {
|
||||
for (int i = 0; i < file->message_type_count(); ++i) {
|
||||
if (HasMapFields(file->message_type(i))) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static bool HasEnumDefinitions(const Descriptor* message_type) {
|
||||
if (message_type->enum_type_count() > 0) return true;
|
||||
for (int i = 0; i < message_type->nested_type_count(); ++i) {
|
||||
@@ -432,6 +526,134 @@ bool HasEnumDefinitions(const FileDescriptor* file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsStringOrMessage(const FieldDescriptor* field) {
|
||||
switch (field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_INT32:
|
||||
case FieldDescriptor::CPPTYPE_INT64:
|
||||
case FieldDescriptor::CPPTYPE_UINT32:
|
||||
case FieldDescriptor::CPPTYPE_UINT64:
|
||||
case FieldDescriptor::CPPTYPE_DOUBLE:
|
||||
case FieldDescriptor::CPPTYPE_FLOAT:
|
||||
case FieldDescriptor::CPPTYPE_BOOL:
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
return false;
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
return true;
|
||||
}
|
||||
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
bool IsAnyMessage(const FileDescriptor* descriptor) {
|
||||
return descriptor->name() == kAnyProtoFile;
|
||||
}
|
||||
|
||||
bool IsAnyMessage(const Descriptor* descriptor) {
|
||||
return descriptor->name() == kAnyMessageName &&
|
||||
descriptor->file()->name() == kAnyProtoFile;
|
||||
}
|
||||
|
||||
bool IsWellKnownMessage(const FileDescriptor* descriptor) {
|
||||
return !descriptor->name().compare(0, 16, kGoogleProtobufPrefix);
|
||||
}
|
||||
|
||||
enum Utf8CheckMode {
|
||||
STRICT = 0, // Parsing will fail if non UTF-8 data is in string fields.
|
||||
VERIFY = 1, // Only log an error but parsing will succeed.
|
||||
NONE = 2, // No UTF-8 check.
|
||||
};
|
||||
|
||||
// Which level of UTF-8 enforcemant is placed on this file.
|
||||
static Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field,
|
||||
const Options& options) {
|
||||
if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
|
||||
return STRICT;
|
||||
} else if (GetOptimizeFor(field->file(), options) !=
|
||||
FileOptions::LITE_RUNTIME) {
|
||||
return VERIFY;
|
||||
} else {
|
||||
return NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateUtf8CheckCode(const FieldDescriptor* field,
|
||||
const Options& options, bool for_parse,
|
||||
const std::map<string, string>& variables,
|
||||
const char* parameters,
|
||||
const char* strict_function,
|
||||
const char* verify_function,
|
||||
io::Printer* printer) {
|
||||
switch (GetUtf8CheckMode(field, options)) {
|
||||
case STRICT: {
|
||||
if (for_parse) {
|
||||
printer->Print("DO_(");
|
||||
}
|
||||
printer->Print(
|
||||
"::google::protobuf::internal::WireFormatLite::$function$(\n",
|
||||
"function", strict_function);
|
||||
printer->Indent();
|
||||
printer->Print(variables, parameters);
|
||||
if (for_parse) {
|
||||
printer->Print("::google::protobuf::internal::WireFormatLite::PARSE,\n");
|
||||
} else {
|
||||
printer->Print("::google::protobuf::internal::WireFormatLite::SERIALIZE,\n");
|
||||
}
|
||||
printer->Print("\"$full_name$\")", "full_name", field->full_name());
|
||||
if (for_parse) {
|
||||
printer->Print(")");
|
||||
}
|
||||
printer->Print(";\n");
|
||||
printer->Outdent();
|
||||
break;
|
||||
}
|
||||
case VERIFY: {
|
||||
printer->Print(
|
||||
"::google::protobuf::internal::WireFormat::$function$(\n",
|
||||
"function", verify_function);
|
||||
printer->Indent();
|
||||
printer->Print(variables, parameters);
|
||||
if (for_parse) {
|
||||
printer->Print("::google::protobuf::internal::WireFormat::PARSE,\n");
|
||||
} else {
|
||||
printer->Print("::google::protobuf::internal::WireFormat::SERIALIZE,\n");
|
||||
}
|
||||
printer->Print("\"$full_name$\");\n", "full_name", field->full_name());
|
||||
printer->Outdent();
|
||||
break;
|
||||
}
|
||||
case NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
|
||||
const Options& options, bool for_parse,
|
||||
const std::map<string, string>& variables,
|
||||
const char* parameters,
|
||||
io::Printer* printer) {
|
||||
GenerateUtf8CheckCode(field, options, for_parse, variables, parameters,
|
||||
"VerifyUtf8String", "VerifyUTF8StringNamedField",
|
||||
printer);
|
||||
}
|
||||
|
||||
void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
|
||||
const Options& options, bool for_parse,
|
||||
const std::map<string, string>& variables,
|
||||
const char* parameters,
|
||||
io::Printer* printer) {
|
||||
GenerateUtf8CheckCode(field, options, for_parse, variables, parameters,
|
||||
"VerifyUtf8Cord", "VerifyUTF8CordNamedField", printer);
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
@@ -0,0 +1,285 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace io {
|
||||
class Printer;
|
||||
}
|
||||
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
// Commonly-used separator comments. Thick is a line of '=', thin is a line
|
||||
// of '-'.
|
||||
extern const char kThickSeparator[];
|
||||
extern const char kThinSeparator[];
|
||||
|
||||
// Returns the non-nested type name for the given type. If "qualified" is
|
||||
// true, prefix the type with the full namespace. For example, if you had:
|
||||
// package foo.bar;
|
||||
// message Baz { message Qux {} }
|
||||
// Then the qualified ClassName for Qux would be:
|
||||
// ::foo::bar::Baz_Qux
|
||||
// While the non-qualified version would be:
|
||||
// Baz_Qux
|
||||
string ClassName(const Descriptor* descriptor, bool qualified);
|
||||
string ClassName(const EnumDescriptor* enum_descriptor, bool qualified);
|
||||
|
||||
// Name of the CRTP class template (for use with proto_h).
|
||||
// This is a class name, like "ProtoName_InternalBase".
|
||||
string DependentBaseClassTemplateName(const Descriptor* descriptor);
|
||||
|
||||
// Name of the base class: either the dependent base class (for use with
|
||||
// proto_h) or google::protobuf::Message.
|
||||
string SuperClassName(const Descriptor* descriptor, const Options& options);
|
||||
|
||||
// Returns a string that down-casts from the dependent base class to the
|
||||
// derived class.
|
||||
string DependentBaseDownCast();
|
||||
string DependentBaseConstDownCast();
|
||||
|
||||
// Get the (unqualified) name that should be used for this field in C++ code.
|
||||
// The name is coerced to lower-case to emulate proto1 behavior. People
|
||||
// should be using lowercase-with-underscores style for proto field names
|
||||
// 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);
|
||||
|
||||
// Returns the scope where the field was defined (for extensions, this is
|
||||
// different from the message type to which the field applies).
|
||||
inline const Descriptor* FieldScope(const FieldDescriptor* field) {
|
||||
return field->is_extension() ?
|
||||
field->extension_scope() : field->containing_type();
|
||||
}
|
||||
|
||||
// Returns true if the given 'field_descriptor' has a message type that is
|
||||
// a dependency of the file where the field is defined (i.e., the field
|
||||
// type is defined in a different file than the message holding the field).
|
||||
//
|
||||
// This only applies to Message-typed fields. Enum-typed fields may refer
|
||||
// to an enum in a dependency; however, enums are specified and
|
||||
// forward-declared with an enum-base, so the definition is not required to
|
||||
// manipulate the field value.
|
||||
bool IsFieldDependent(const FieldDescriptor* field_descriptor);
|
||||
|
||||
// Returns the name that should be used for forcing dependent lookup from a
|
||||
// dependent base class.
|
||||
string DependentTypeName(const FieldDescriptor* field);
|
||||
|
||||
// Returns the fully-qualified type name field->message_type(). Usually this
|
||||
// is just ClassName(field->message_type(), true);
|
||||
string FieldMessageTypeName(const FieldDescriptor* field);
|
||||
|
||||
// Strips ".proto" or ".protodevel" from the end of a filename.
|
||||
LIBPROTOC_EXPORT string StripProto(const string& filename);
|
||||
|
||||
// Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.).
|
||||
// Note: non-built-in type names will be qualified, meaning they will start
|
||||
// with a ::. If you are using the type as a template parameter, you will
|
||||
// need to insure there is a space between the < and the ::, because the
|
||||
// ridiculous C++ standard defines "<:" to be a synonym for "[".
|
||||
const char* PrimitiveTypeName(FieldDescriptor::CppType type);
|
||||
|
||||
// Get the declared type name in CamelCase format, as is used e.g. for the
|
||||
// methods of WireFormat. For example, TYPE_INT32 becomes "Int32".
|
||||
const char* DeclaredTypeMethodName(FieldDescriptor::Type type);
|
||||
|
||||
// Return the code that evaluates to the number when compiled.
|
||||
string Int32ToString(int number);
|
||||
|
||||
// Return the code that evaluates to the number when compiled.
|
||||
string Int64ToString(int64 number);
|
||||
|
||||
// Get code that evaluates to the field's default value.
|
||||
string DefaultValue(const FieldDescriptor* field);
|
||||
|
||||
// Convert a file name into a valid identifier.
|
||||
string FilenameIdentifier(const string& filename);
|
||||
|
||||
// For each .proto file generates a unique namespace. In this namespace global
|
||||
// definitions are put to prevent collisions.
|
||||
string FileLevelNamespace(const string& filename);
|
||||
|
||||
// Return the qualified C++ name for a file level symbol.
|
||||
string QualifiedFileLevelSymbol(const string& package, const string& name);
|
||||
|
||||
// Escape C++ trigraphs by escaping question marks to \?
|
||||
string EscapeTrigraphs(const string& to_escape);
|
||||
|
||||
// Escaped function name to eliminate naming conflict.
|
||||
string SafeFunctionName(const Descriptor* descriptor,
|
||||
const FieldDescriptor* field,
|
||||
const string& prefix);
|
||||
|
||||
// Returns true if unknown fields are preseved after parsing.
|
||||
inline bool PreserveUnknownFields(const Descriptor* message) {
|
||||
return message->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
|
||||
}
|
||||
|
||||
// Returns the optimize mode for <file>, respecting <options.enforce_lite>.
|
||||
::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor(
|
||||
const FileDescriptor* file, const Options& options);
|
||||
|
||||
// If PreserveUnknownFields() is true, determines whether unknown
|
||||
// fields will be stored in an UnknownFieldSet or a string.
|
||||
// If PreserveUnknownFields() is false, this method will not be
|
||||
// used.
|
||||
inline bool UseUnknownFieldSet(const FileDescriptor* file,
|
||||
const Options& options) {
|
||||
return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
|
||||
|
||||
// Does the file have any map fields, necessitating the file to include
|
||||
// map_field_inl.h and map.h.
|
||||
bool HasMapFields(const FileDescriptor* file);
|
||||
|
||||
// Does this file have any enum type definitions?
|
||||
bool HasEnumDefinitions(const FileDescriptor* file);
|
||||
|
||||
// Does this file have generated parsing, serialization, and other
|
||||
// standard methods for which reflection-based fallback implementations exist?
|
||||
inline bool HasGeneratedMethods(const FileDescriptor* file,
|
||||
const Options& options) {
|
||||
return GetOptimizeFor(file, options) != FileOptions::CODE_SIZE;
|
||||
}
|
||||
|
||||
// Do message classes in this file have descriptor and reflection methods?
|
||||
inline bool HasDescriptorMethods(const FileDescriptor* file,
|
||||
const Options& options) {
|
||||
return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
|
||||
// Should we generate generic services for this file?
|
||||
inline bool HasGenericServices(const FileDescriptor* file,
|
||||
const Options& options) {
|
||||
return file->service_count() > 0 &&
|
||||
GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME &&
|
||||
file->options().cc_generic_services();
|
||||
}
|
||||
|
||||
// Should we generate a separate, super-optimized code path for serializing to
|
||||
// flat arrays? We don't do this in Lite mode because we'd rather reduce code
|
||||
// size.
|
||||
inline bool HasFastArraySerialization(const FileDescriptor* file,
|
||||
const Options& options) {
|
||||
return GetOptimizeFor(file, options) == FileOptions::SPEED;
|
||||
}
|
||||
|
||||
// Returns whether we have to generate code with static initializers.
|
||||
bool StaticInitializersForced(const FileDescriptor* file,
|
||||
const Options& options);
|
||||
|
||||
|
||||
inline bool IsMapEntryMessage(const Descriptor* descriptor) {
|
||||
return descriptor->options().map_entry();
|
||||
}
|
||||
|
||||
// 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) {
|
||||
return file->syntax() != FileDescriptor::SYNTAX_PROTO3;
|
||||
}
|
||||
|
||||
// Returns true if 'enum' semantics are such that unknown values are preserved
|
||||
// in the enum field itself, rather than going to the UnknownFieldSet.
|
||||
inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) {
|
||||
return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
|
||||
}
|
||||
|
||||
inline bool SupportsArenas(const FileDescriptor* file) {
|
||||
return file->options().cc_enable_arenas();
|
||||
}
|
||||
|
||||
inline bool SupportsArenas(const Descriptor* desc) {
|
||||
return SupportsArenas(desc->file());
|
||||
}
|
||||
|
||||
inline bool SupportsArenas(const FieldDescriptor* field) {
|
||||
return SupportsArenas(field->file());
|
||||
}
|
||||
|
||||
bool IsAnyMessage(const FileDescriptor* descriptor);
|
||||
bool IsAnyMessage(const Descriptor* descriptor);
|
||||
|
||||
bool IsWellKnownMessage(const FileDescriptor* descriptor);
|
||||
|
||||
void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
|
||||
const Options& options, bool for_parse,
|
||||
const std::map<string, string>& variables,
|
||||
const char* parameters,
|
||||
io::Printer* printer);
|
||||
|
||||
void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
|
||||
const Options& options, bool for_parse,
|
||||
const std::map<string, string>& variables,
|
||||
const char* parameters, io::Printer* printer);
|
||||
|
||||
inline ::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor(
|
||||
const FileDescriptor* file, const Options& options) {
|
||||
return options.enforce_lite
|
||||
? FileOptions::LITE_RUNTIME
|
||||
: file->options().optimize_for();
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
|
||||
@@ -0,0 +1,446 @@
|
||||
// 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/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 {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
bool IsProto3Field(const FieldDescriptor* field_descriptor) {
|
||||
const FileDescriptor* file_descriptor = field_descriptor->file();
|
||||
return file_descriptor->syntax() == FileDescriptor::SYNTAX_PROTO3;
|
||||
}
|
||||
|
||||
void SetMessageVariables(const FieldDescriptor* descriptor,
|
||||
std::map<string, string>* variables,
|
||||
const Options& options) {
|
||||
SetCommonFieldVariables(descriptor, variables, options);
|
||||
(*variables)["type"] = ClassName(descriptor->message_type(), false);
|
||||
(*variables)["file_namespace"] =
|
||||
FileLevelNamespace(descriptor->file()->name());
|
||||
(*variables)["stream_writer"] =
|
||||
(*variables)["declared_type"] +
|
||||
(HasFastArraySerialization(descriptor->message_type()->file(), options)
|
||||
? "MaybeToArray"
|
||||
: "");
|
||||
(*variables)["full_name"] = descriptor->full_name();
|
||||
|
||||
const FieldDescriptor* key =
|
||||
descriptor->message_type()->FindFieldByName("key");
|
||||
const FieldDescriptor* val =
|
||||
descriptor->message_type()->FindFieldByName("value");
|
||||
(*variables)["key_cpp"] = PrimitiveTypeName(key->cpp_type());
|
||||
switch (val->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
(*variables)["val_cpp"] = FieldMessageTypeName(val);
|
||||
(*variables)["wrapper"] = "EntryWrapper";
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
(*variables)["val_cpp"] = ClassName(val->enum_type(), true);
|
||||
(*variables)["wrapper"] = "EnumEntryWrapper";
|
||||
break;
|
||||
default:
|
||||
(*variables)["val_cpp"] = PrimitiveTypeName(val->cpp_type());
|
||||
(*variables)["wrapper"] = "EntryWrapper";
|
||||
}
|
||||
(*variables)["key_wire_type"] =
|
||||
"::google::protobuf::internal::WireFormatLite::TYPE_" +
|
||||
ToUpper(DeclaredTypeMethodName(key->type()));
|
||||
(*variables)["val_wire_type"] =
|
||||
"::google::protobuf::internal::WireFormatLite::TYPE_" +
|
||||
ToUpper(DeclaredTypeMethodName(val->type()));
|
||||
(*variables)["map_classname"] = ClassName(descriptor->message_type(), false);
|
||||
(*variables)["number"] = SimpleItoa(descriptor->number());
|
||||
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
|
||||
|
||||
if (HasDescriptorMethods(descriptor->file(), options)) {
|
||||
(*variables)["lite"] = "";
|
||||
} else {
|
||||
(*variables)["lite"] = "Lite";
|
||||
}
|
||||
|
||||
if (!IsProto3Field(descriptor) &&
|
||||
val->type() == FieldDescriptor::TYPE_ENUM) {
|
||||
const EnumValueDescriptor* default_value = val->default_value_enum();
|
||||
(*variables)["default_enum_value"] = Int32ToString(default_value->number());
|
||||
} else {
|
||||
(*variables)["default_enum_value"] = "0";
|
||||
}
|
||||
}
|
||||
|
||||
MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: FieldGenerator(options),
|
||||
descriptor_(descriptor),
|
||||
dependent_field_(options.proto_h && IsFieldDependent(descriptor)) {
|
||||
SetMessageVariables(descriptor, &variables_, options);
|
||||
}
|
||||
|
||||
MapFieldGenerator::~MapFieldGenerator() {}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GeneratePrivateMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"typedef ::google::protobuf::internal::MapEntryLite<\n"
|
||||
" $key_cpp$, $val_cpp$,\n"
|
||||
" $key_wire_type$,\n"
|
||||
" $val_wire_type$,\n"
|
||||
" $default_enum_value$ >\n"
|
||||
" $map_classname$;\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_,
|
||||
"$deprecated_attr$const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
|
||||
" $name$() const;\n"
|
||||
"$deprecated_attr$::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
|
||||
" mutable_$name$();\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer,
|
||||
bool is_inline) const {
|
||||
std::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"
|
||||
"$classname$::mutable_$name$() {\n"
|
||||
" // @@protoc_insertion_point(field_mutable_map:$full_name$)\n"
|
||||
" return $name$_.MutableMap();\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
std::map<string, string> variables(variables_);
|
||||
variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
|
||||
printer->Print(variables, "$this_message$$name$_.Clear();\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateMergingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||
printer->Print(variables_,
|
||||
"$name$_.SetAssignDescriptorCallback(\n"
|
||||
" $file_namespace$::protobuf_AssignDescriptorsOnce);\n"
|
||||
"$name$_.SetEntryDescriptor(\n"
|
||||
" &$type$_descriptor);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateCopyConstructorCode(io::Printer* printer) const {
|
||||
GenerateConstructorCode(printer);
|
||||
GenerateMergingCode(printer);
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
const FieldDescriptor* key_field =
|
||||
descriptor_->message_type()->FindFieldByName("key");
|
||||
const FieldDescriptor* value_field =
|
||||
descriptor_->message_type()->FindFieldByName("value");
|
||||
bool using_entry = false;
|
||||
string key;
|
||||
string value;
|
||||
if (IsProto3Field(descriptor_) ||
|
||||
value_field->type() != FieldDescriptor::TYPE_ENUM) {
|
||||
printer->Print(variables_,
|
||||
"$map_classname$::Parser< ::google::protobuf::internal::MapField$lite$<\n"
|
||||
" $key_cpp$, $val_cpp$,\n"
|
||||
" $key_wire_type$,\n"
|
||||
" $val_wire_type$,\n"
|
||||
" $default_enum_value$ >,\n"
|
||||
" ::google::protobuf::Map< $key_cpp$, $val_cpp$ > >"
|
||||
" parser(&$name$_);\n"
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
|
||||
" input, &parser));\n");
|
||||
key = "parser.key()";
|
||||
value = "parser.value()";
|
||||
} else {
|
||||
using_entry = true;
|
||||
key = "entry->key()";
|
||||
value = "entry->value()";
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::scoped_ptr<$map_classname$> entry($name$_.NewEntry());\n");
|
||||
printer->Print(variables_,
|
||||
"{\n"
|
||||
" ::std::string data;\n"
|
||||
" DO_(::google::protobuf::internal::WireFormatLite::ReadString(input, &data));\n"
|
||||
" DO_(entry->ParseFromString(data));\n"
|
||||
" if ($val_cpp$_IsValid(*entry->mutable_value())) {\n"
|
||||
" (*mutable_$name$())[entry->key()] =\n"
|
||||
" static_cast< $val_cpp$ >(*entry->mutable_value());\n"
|
||||
" } else {\n");
|
||||
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||
printer->Print(variables_,
|
||||
" mutable_unknown_fields()"
|
||||
"->AddLengthDelimited($number$, data);\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" unknown_fields_stream.WriteVarint32($tag$u);\n"
|
||||
" unknown_fields_stream.WriteVarint32(data.size());\n"
|
||||
" unknown_fields_stream.WriteString(data);\n");
|
||||
}
|
||||
|
||||
printer->Print(variables_,
|
||||
" }\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
if (key_field->type() == FieldDescriptor::TYPE_STRING) {
|
||||
GenerateUtf8CheckCodeForString(
|
||||
key_field, options_, true, variables_,
|
||||
StrCat(key, ".data(), ", key, ".length(),\n").data(), printer);
|
||||
}
|
||||
if (value_field->type() == FieldDescriptor::TYPE_STRING) {
|
||||
GenerateUtf8CheckCodeForString(value_field, options_, true, variables_,
|
||||
StrCat(value, ".data(), ", value, ".length(),\n").data(), printer);
|
||||
}
|
||||
|
||||
// If entry is allocated by arena, its desctructor should be avoided.
|
||||
if (using_entry && SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables_,
|
||||
"if (entry->GetArena() != NULL) entry.release();\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateSerializationLoop(io::Printer* printer,
|
||||
const std::map<string, string>& variables,
|
||||
bool supports_arenas,
|
||||
const string& utf8_check,
|
||||
const string& loop_header,
|
||||
const string& ptr,
|
||||
bool loop_via_iterators) {
|
||||
printer->Print(variables,
|
||||
StrCat("::google::protobuf::scoped_ptr<$map_classname$> entry;\n",
|
||||
loop_header, " {\n").c_str());
|
||||
printer->Indent();
|
||||
|
||||
printer->Print(variables, StrCat(
|
||||
"entry.reset($name$_.New$wrapper$(\n"
|
||||
" ", ptr, "->first, ", ptr, "->second));\n"
|
||||
"$write_entry$;\n").c_str());
|
||||
|
||||
// If entry is allocated by arena, its desctructor should be avoided.
|
||||
if (supports_arenas) {
|
||||
printer->Print(
|
||||
"if (entry->GetArena() != NULL) {\n"
|
||||
" entry.release();\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
if (!utf8_check.empty()) {
|
||||
// If loop_via_iterators is true then ptr is actually an iterator, and we
|
||||
// create a pointer by prefixing it with "&*".
|
||||
printer->Print(
|
||||
StrCat(utf8_check, "(", (loop_via_iterators ? "&*" : ""), ptr, ");\n")
|
||||
.c_str());
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
std::map<string, string> variables(variables_);
|
||||
variables["write_entry"] = "::google::protobuf::internal::WireFormatLite::Write" +
|
||||
variables["stream_writer"] + "(\n " +
|
||||
variables["number"] + ", *entry, output)";
|
||||
variables["deterministic"] = "output->IsSerializationDeterministic()";
|
||||
GenerateSerializeWithCachedSizes(printer, variables);
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
std::map<string, string> variables(variables_);
|
||||
variables["write_entry"] =
|
||||
"target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" InternalWrite" + variables["declared_type"] +
|
||||
"NoVirtualToArray(\n " + variables["number"] +
|
||||
", *entry, deterministic, target);\n";
|
||||
variables["deterministic"] = "deterministic";
|
||||
GenerateSerializeWithCachedSizes(printer, variables);
|
||||
}
|
||||
|
||||
void MapFieldGenerator::GenerateSerializeWithCachedSizes(
|
||||
io::Printer* printer, const std::map<string, string>& variables) const {
|
||||
printer->Print(variables,
|
||||
"if (!this->$name$().empty()) {\n");
|
||||
printer->Indent();
|
||||
const FieldDescriptor* key_field =
|
||||
descriptor_->message_type()->FindFieldByName("key");
|
||||
const FieldDescriptor* value_field =
|
||||
descriptor_->message_type()->FindFieldByName("value");
|
||||
const bool string_key = key_field->type() == FieldDescriptor::TYPE_STRING;
|
||||
const bool string_value = value_field->type() == FieldDescriptor::TYPE_STRING;
|
||||
|
||||
printer->Print(variables,
|
||||
"typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_pointer\n"
|
||||
" ConstPtr;\n");
|
||||
if (string_key) {
|
||||
printer->Print(variables,
|
||||
"typedef ConstPtr SortItem;\n"
|
||||
"typedef ::google::protobuf::internal::"
|
||||
"CompareByDerefFirst<SortItem> Less;\n");
|
||||
} else {
|
||||
printer->Print(variables,
|
||||
"typedef ::google::protobuf::internal::SortItem< $key_cpp$, ConstPtr > "
|
||||
"SortItem;\n"
|
||||
"typedef ::google::protobuf::internal::CompareByFirstField<SortItem> Less;\n");
|
||||
}
|
||||
string utf8_check;
|
||||
if (string_key || string_value) {
|
||||
printer->Print(
|
||||
"struct Utf8Check {\n"
|
||||
" static void Check(ConstPtr p) {\n");
|
||||
printer->Indent();
|
||||
printer->Indent();
|
||||
if (string_key) {
|
||||
GenerateUtf8CheckCodeForString(key_field, options_, false, variables,
|
||||
"p->first.data(), p->first.length(),\n",
|
||||
printer);
|
||||
}
|
||||
if (string_value) {
|
||||
GenerateUtf8CheckCodeForString(value_field, options_, false, variables,
|
||||
"p->second.data(), p->second.length(),\n",
|
||||
printer);
|
||||
}
|
||||
printer->Outdent();
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
" }\n"
|
||||
"};\n");
|
||||
utf8_check = "Utf8Check::Check";
|
||||
}
|
||||
|
||||
printer->Print(variables,
|
||||
"\n"
|
||||
"if ($deterministic$ &&\n"
|
||||
" this->$name$().size() > 1) {\n"
|
||||
" ::google::protobuf::scoped_array<SortItem> items(\n"
|
||||
" new SortItem[this->$name$().size()]);\n"
|
||||
" typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::size_type size_type;\n"
|
||||
" size_type n = 0;\n"
|
||||
" for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
|
||||
" it = this->$name$().begin();\n"
|
||||
" it != this->$name$().end(); ++it, ++n) {\n"
|
||||
" items[n] = SortItem(&*it);\n"
|
||||
" }\n"
|
||||
" ::std::sort(&items[0], &items[n], Less());\n");
|
||||
printer->Indent();
|
||||
GenerateSerializationLoop(printer, variables, SupportsArenas(descriptor_),
|
||||
utf8_check, "for (size_type i = 0; i < n; i++)",
|
||||
string_key ? "items[i]" : "items[i].second", false);
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"} else {\n");
|
||||
printer->Indent();
|
||||
GenerateSerializationLoop(
|
||||
printer, variables, SupportsArenas(descriptor_), utf8_check,
|
||||
"for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
|
||||
" it = this->$name$().begin();\n"
|
||||
" it != this->$name$().end(); ++it)",
|
||||
"it", true);
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ *\n"
|
||||
" ::google::protobuf::internal::FromIntSize(this->$name$_size());\n"
|
||||
"{\n"
|
||||
" ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
|
||||
" for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
|
||||
" it = this->$name$().begin();\n"
|
||||
" it != this->$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");
|
||||
|
||||
// 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
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
+19
-42
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -28,72 +28,49 @@
|
||||
// (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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_message_field.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
class MessageFieldGenerator : public FieldGenerator {
|
||||
class MapFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
explicit MessageFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~MessageFieldGenerator();
|
||||
MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
|
||||
~MapFieldGenerator();
|
||||
|
||||
// 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;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
// A helper for GenerateSerializeWithCachedSizes{,ToArray}.
|
||||
void GenerateSerializeWithCachedSizes(
|
||||
io::Printer* printer, const std::map<string, string>& variables) const;
|
||||
|
||||
const FieldDescriptor* descriptor_;
|
||||
map<string, string> variables_;
|
||||
const bool dependent_field_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
|
||||
};
|
||||
|
||||
class RepeatedMessageFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~RepeatedMessageFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
void GenerateMergingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
const FieldDescriptor* descriptor_;
|
||||
map<string, string> variables_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
@@ -101,4 +78,4 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__
|
||||
File diff suppressed because it is too large
Load Diff
+78
-28
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -35,8 +35,12 @@
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
|
||||
|
||||
#include <memory>
|
||||
#ifndef _SHARED_PTR_H
|
||||
#include <google/protobuf/stubs/shared_ptr.h>
|
||||
#endif
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||
|
||||
@@ -57,39 +61,38 @@ class ExtensionGenerator; // extension.h
|
||||
class MessageGenerator {
|
||||
public:
|
||||
// See generator.cc for the meaning of dllexport_decl.
|
||||
explicit MessageGenerator(const Descriptor* descriptor,
|
||||
const Options& options);
|
||||
MessageGenerator(const Descriptor* descriptor, const Options& options);
|
||||
~MessageGenerator();
|
||||
|
||||
// Appends the pre-order walk of the nested generators to list.
|
||||
void Flatten(std::vector<MessageGenerator*>* list);
|
||||
// Append the two types of nested generators to the corresponding vector.
|
||||
void AddGenerators(std::vector<EnumGenerator*>* enum_generators,
|
||||
std::vector<ExtensionGenerator*>* extension_generators);
|
||||
|
||||
// Header stuff.
|
||||
|
||||
// Generate foward declarations for this class and all its nested types.
|
||||
void GenerateForwardDeclaration(io::Printer* printer);
|
||||
|
||||
// Generate definitions of all nested enums (must come before class
|
||||
// definitions because those classes use the enums definitions).
|
||||
void GenerateEnumDefinitions(io::Printer* printer);
|
||||
|
||||
// Generate specializations of GetEnumDescriptor<MyEnum>().
|
||||
// Precondition: in ::google::protobuf namespace.
|
||||
void GenerateGetEnumDescriptorSpecializations(io::Printer* printer);
|
||||
// Return names for forward declarations of this class and all its nested
|
||||
// types. A given key in {class,enum}_names will map from a class name to the
|
||||
// descriptor that was responsible for its inclusion in the map. This can be
|
||||
// used to associate the descriptor with the code generated for it.
|
||||
void FillMessageForwardDeclarations(
|
||||
std::map<string, const Descriptor*>* class_names);
|
||||
|
||||
// Generate definitions for this class and all its nested types.
|
||||
void GenerateClassDefinition(io::Printer* printer);
|
||||
|
||||
// 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);
|
||||
|
||||
// Dependent methods are always inline.
|
||||
void GenerateDependentInlineMethods(io::Printer* printer);
|
||||
|
||||
// Source file stuff.
|
||||
|
||||
// Generate code which declares all the global descriptor pointers which
|
||||
// will be initialized by the methods below.
|
||||
void GenerateDescriptorDeclarations(io::Printer* printer);
|
||||
|
||||
// Generate code that initializes the global variable storing the message's
|
||||
// descriptor.
|
||||
void GenerateDescriptorInitializer(io::Printer* printer, int index);
|
||||
// Generate extra fields
|
||||
void GenerateExtraDefaultFields(io::Printer* printer);
|
||||
|
||||
// Generate code that calls MessageFactory::InternalRegisterGeneratedMessage()
|
||||
// for all types.
|
||||
@@ -112,11 +115,16 @@ class MessageGenerator {
|
||||
|
||||
private:
|
||||
// Generate declarations and definitions of accessors for fields.
|
||||
void GenerateDependentBaseClassDefinition(io::Printer* printer);
|
||||
void GenerateDependentFieldAccessorDeclarations(io::Printer* printer);
|
||||
void GenerateFieldAccessorDeclarations(io::Printer* printer);
|
||||
void GenerateFieldAccessorDefinitions(io::Printer* printer);
|
||||
void GenerateDependentFieldAccessorDefinitions(io::Printer* printer);
|
||||
void GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline);
|
||||
|
||||
// Generate the field offsets array.
|
||||
void GenerateOffsets(io::Printer* printer);
|
||||
// Generate the field offsets array. Returns the a pair of the total numer
|
||||
// of entries generated and the index of the first has_bit entry.
|
||||
std::pair<size_t, size_t> GenerateOffsets(io::Printer* printer);
|
||||
void GenerateSchema(io::Printer* printer, int offset, int has_offset);
|
||||
|
||||
// Generate constructors and destructor.
|
||||
void GenerateStructors(io::Printer* printer);
|
||||
@@ -129,9 +137,12 @@ class MessageGenerator {
|
||||
void GenerateSharedConstructorCode(io::Printer* printer);
|
||||
// Generate the shared destructor code.
|
||||
void GenerateSharedDestructorCode(io::Printer* printer);
|
||||
// Generate the arena-specific destructor code.
|
||||
void GenerateArenaDestructorCode(io::Printer* printer);
|
||||
|
||||
// Generate standard Message methods.
|
||||
void GenerateClear(io::Printer* printer);
|
||||
void GenerateOneofClear(io::Printer* printer);
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer);
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer);
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer);
|
||||
@@ -147,19 +158,58 @@ class MessageGenerator {
|
||||
void GenerateSerializeOneField(io::Printer* printer,
|
||||
const FieldDescriptor* field,
|
||||
bool unbounded);
|
||||
// Generate a switch statement to serialize 2+ fields from the same oneof.
|
||||
// Or, if fields.size() == 1, just call GenerateSerializeOneField().
|
||||
void GenerateSerializeOneofFields(
|
||||
io::Printer* printer, const std::vector<const FieldDescriptor*>& fields,
|
||||
bool to_array);
|
||||
void GenerateSerializeOneExtensionRange(
|
||||
io::Printer* printer, const Descriptor::ExtensionRange* range,
|
||||
bool unbounded);
|
||||
|
||||
|
||||
// Generates has_foo() functions and variables for singular field has-bits.
|
||||
void GenerateSingularFieldHasBits(const FieldDescriptor* field,
|
||||
std::map<string, string> vars,
|
||||
io::Printer* printer);
|
||||
// Generates has_foo() functions and variables for oneof field has-bits.
|
||||
void GenerateOneofHasBits(io::Printer* printer, bool is_inline);
|
||||
// Generates has_foo_bar() functions for oneof members.
|
||||
void GenerateOneofMemberHasBits(const FieldDescriptor* field,
|
||||
const std::map<string, string>& vars,
|
||||
io::Printer* printer);
|
||||
// Generates the clear_foo() method for a field.
|
||||
void GenerateFieldClear(const FieldDescriptor* field,
|
||||
const std::map<string, string>& vars,
|
||||
io::Printer* printer);
|
||||
|
||||
void GenerateConstructorBody(io::Printer* printer,
|
||||
std::vector<bool> already_processed,
|
||||
bool copy_constructor) const;
|
||||
|
||||
size_t HasBitsSize() const;
|
||||
std::vector<uint32> RequiredFieldsBitMask() const;
|
||||
|
||||
const Descriptor* descriptor_;
|
||||
string classname_;
|
||||
Options options_;
|
||||
FieldGeneratorMap field_generators_;
|
||||
scoped_array<scoped_ptr<MessageGenerator> > nested_generators_;
|
||||
scoped_array<scoped_ptr<EnumGenerator> > enum_generators_;
|
||||
scoped_array<scoped_ptr<ExtensionGenerator> > extension_generators_;
|
||||
// optimized_order_ is the order we layout the message's fields in the class.
|
||||
// This is reused to initialize the fields in-order for cache efficiency.
|
||||
//
|
||||
// optimized_order_ excludes oneof fields.
|
||||
std::vector<const FieldDescriptor *> optimized_order_;
|
||||
std::vector<int> has_bit_indices_;
|
||||
int max_has_bit_index_;
|
||||
google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > nested_generators_;
|
||||
google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_;
|
||||
google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_;
|
||||
int num_required_fields_;
|
||||
bool use_dependent_base_;
|
||||
|
||||
int index_in_metadata_;
|
||||
|
||||
friend class FileGenerator;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,159 @@
|
||||
// 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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
class MessageFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
MessageFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~MessageFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||
void GenerateDependentAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateDependentInlineAccessorDefinitions(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 GenerateMessageClearingCode(io::Printer* printer) const;
|
||||
void GenerateMergingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateDestructorCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
|
||||
protected:
|
||||
void GenerateArenaManipulationCode(const std::map<string, string>& variables,
|
||||
io::Printer* printer) const;
|
||||
|
||||
virtual void GenerateGetterDeclaration(io::Printer* printer) const;
|
||||
|
||||
const FieldDescriptor* descriptor_;
|
||||
const bool dependent_field_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
|
||||
};
|
||||
|
||||
class MessageOneofFieldGenerator : public MessageFieldGenerator {
|
||||
public:
|
||||
MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~MessageOneofFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GenerateDependentAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateDependentInlineAccessorDefinitions(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;
|
||||
|
||||
// MessageFieldGenerator, from which we inherit, overrides this so we need to
|
||||
// override it as well.
|
||||
void GenerateMessageClearingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateDestructorCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
|
||||
protected:
|
||||
void GenerateGetterDeclaration(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
void InternalGenerateInlineAccessorDefinitions(
|
||||
const std::map<string, string>& variables, io::Printer* printer) const;
|
||||
|
||||
const bool dependent_base_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
|
||||
};
|
||||
|
||||
class RepeatedMessageFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~RepeatedMessageFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||
void GenerateDependentAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateDependentInlineAccessorDefinitions(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;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const {}
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
void InternalGenerateTypeDependentAccessorDeclarations(
|
||||
io::Printer* printer) const;
|
||||
|
||||
const FieldDescriptor* descriptor_;
|
||||
const bool dependent_field_;
|
||||
const bool dependent_getter_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
|
||||
+15
-4
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -41,12 +41,23 @@ namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
// Generator options:
|
||||
// Generator options (see generator.cc for a description of each):
|
||||
struct Options {
|
||||
Options() : safe_boundary_check(false) {
|
||||
}
|
||||
Options()
|
||||
: safe_boundary_check(false),
|
||||
proto_h(false),
|
||||
allow_import_public(true),
|
||||
annotate_headers(false),
|
||||
enforce_lite(false) {}
|
||||
|
||||
string dllexport_decl;
|
||||
bool safe_boundary_check;
|
||||
bool proto_h;
|
||||
bool allow_import_public;
|
||||
bool annotate_headers;
|
||||
bool enforce_lite;
|
||||
string annotation_pragma_name;
|
||||
string annotation_guard_name;
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
@@ -0,0 +1,252 @@
|
||||
// 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)
|
||||
//
|
||||
// TODO(kenton): Share code with the versions of this test in other languages?
|
||||
// It seemed like parameterizing it would add more complexity than it is
|
||||
// worth.
|
||||
|
||||
#include <memory>
|
||||
#ifndef _SHARED_PTR_H
|
||||
#include <google/protobuf/stubs/shared_ptr.h>
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_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/file.h>
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/testing/googletest.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
namespace {
|
||||
|
||||
class TestGenerator : public CodeGenerator {
|
||||
public:
|
||||
TestGenerator() {}
|
||||
~TestGenerator() {}
|
||||
|
||||
virtual bool Generate(const FileDescriptor* file,
|
||||
const string& parameter,
|
||||
GeneratorContext* context,
|
||||
string* error) const {
|
||||
TryInsert("test.pb.h", "includes", context);
|
||||
TryInsert("test.pb.h", "namespace_scope", context);
|
||||
TryInsert("test.pb.h", "global_scope", context);
|
||||
TryInsert("test.pb.h", "class_scope:foo.Bar", context);
|
||||
TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", context);
|
||||
|
||||
TryInsert("test.pb.cc", "includes", context);
|
||||
TryInsert("test.pb.cc", "namespace_scope", context);
|
||||
TryInsert("test.pb.cc", "global_scope", context);
|
||||
|
||||
// Check field accessors for an optional int32:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.optInt", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.optInt", context);
|
||||
|
||||
// Check field accessors for a repeated int32:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.repeatedInt", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.repeatedInt", context);
|
||||
|
||||
// Check field accessors for a required string:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.requiredString", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.requiredString", context);
|
||||
TryInsert("test.pb.h", "field_set_char:foo.Bar.requiredString", context);
|
||||
TryInsert("test.pb.h", "field_set_pointer:foo.Bar.requiredString", context);
|
||||
TryInsert("test.pb.h", "field_mutable:foo.Bar.requiredString", context);
|
||||
TryInsert("test.pb.h", "field_set_allocated:foo.Bar.requiredString",
|
||||
context);
|
||||
TryInsert("test.pb.h", "field_set_char:foo.Bar.requiredString", context);
|
||||
TryInsert("test.pb.h", "field_set_pointer:foo.Bar.requiredString", context);
|
||||
|
||||
// Check field accessors for a repeated string:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.repeatedString", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.repeatedString", context);
|
||||
TryInsert("test.pb.h", "field_set_char:foo.Bar.repeatedString", context);
|
||||
TryInsert("test.pb.h", "field_set_pointer:foo.Bar.repeatedString", context);
|
||||
TryInsert("test.pb.h", "field_mutable:foo.Bar.repeatedString", context);
|
||||
TryInsert("test.pb.h", "field_set_char:foo.Bar.repeatedString", context);
|
||||
TryInsert("test.pb.h", "field_set_pointer:foo.Bar.repeatedString", context);
|
||||
|
||||
// Check field accessors for an int inside oneof{}:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.oneOfInt", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.oneOfInt", context);
|
||||
|
||||
// Check field accessors for a string inside oneof{}:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.oneOfString", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.oneOfString", context);
|
||||
TryInsert("test.pb.h", "field_set_char:foo.Bar.oneOfString", context);
|
||||
TryInsert("test.pb.h", "field_set_pointer:foo.Bar.oneOfString", context);
|
||||
TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfString", context);
|
||||
TryInsert("test.pb.h", "field_set_allocated:foo.Bar.oneOfString", context);
|
||||
TryInsert("test.pb.h", "field_set_char:foo.Bar.oneOfString", context);
|
||||
TryInsert("test.pb.h", "field_set_pointer:foo.Bar.oneOfString", context);
|
||||
|
||||
// Check field accessors for an optional message:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.optMessage", context);
|
||||
TryInsert("test.pb.h", "field_mutable:foo.Bar.optMessage", context);
|
||||
TryInsert("test.pb.h", "field_set_allocated:foo.Bar.optMessage", context);
|
||||
|
||||
// Check field accessors for a repeated message:
|
||||
TryInsert("test.pb.h", "field_add:foo.Bar.repeatedMessage", context);
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.repeatedMessage", context);
|
||||
TryInsert("test.pb.h", "field_list:foo.Bar.repeatedMessage", context);
|
||||
TryInsert("test.pb.h", "field_mutable:foo.Bar.repeatedMessage", context);
|
||||
TryInsert("test.pb.h", "field_mutable_list:foo.Bar.repeatedMessage",
|
||||
context);
|
||||
|
||||
// Check field accessors for a message inside oneof{}:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.oneOfMessage", context);
|
||||
TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfMessage", context);
|
||||
TryInsert("test.pb.h", "field_set_allocated:foo.Bar.oneOfMessage", context);
|
||||
|
||||
// Check field accessors for an optional enum:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.optEnum", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.optEnum", context);
|
||||
|
||||
// Check field accessors for a repeated enum:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.repeatedEnum", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.repeatedEnum", context);
|
||||
TryInsert("test.pb.h", "field_add:foo.Bar.repeatedEnum", context);
|
||||
TryInsert("test.pb.h", "field_list:foo.Bar.repeatedEnum", context);
|
||||
TryInsert("test.pb.h", "field_mutable_list:foo.Bar.repeatedEnum", context);
|
||||
|
||||
// Check field accessors for an enum inside oneof{}:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.oneOfEnum", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.oneOfEnum", context);
|
||||
|
||||
// Check field accessors for a required cord:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.requiredCord", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.requiredCord", context);
|
||||
TryInsert("test.pb.h", "field_mutable:foo.Bar.requiredCord", context);
|
||||
|
||||
// Check field accessors for a repeated cord:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.repeatedCord", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.repeatedCord", context);
|
||||
TryInsert("test.pb.h", "field_add:foo.Bar.repeatedCord", context);
|
||||
TryInsert("test.pb.h", "field_list:foo.Bar.repeatedCord", context);
|
||||
TryInsert("test.pb.h", "field_mutable:foo.Bar.repeatedCord", context);
|
||||
TryInsert("test.pb.h", "field_mutable_list:foo.Bar.repeatedCord", context);
|
||||
|
||||
// Check field accessors for a cord inside oneof{}:
|
||||
TryInsert("test.pb.h", "field_get:foo.Bar.oneOfCord", context);
|
||||
TryInsert("test.pb.h", "field_set:foo.Bar.oneOfCord", context);
|
||||
TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfCord", context);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TryInsert(const string& filename, const string& insertion_point,
|
||||
GeneratorContext* context) const {
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
context->OpenForInsert(filename, insertion_point));
|
||||
io::Printer printer(output.get(), '$');
|
||||
printer.Print("// inserted $name$\n", "name", insertion_point);
|
||||
}
|
||||
};
|
||||
|
||||
// This test verifies that all the expected insertion points exist. It does
|
||||
// not verify that they are correctly-placed; that would require actually
|
||||
// compiling the output which is a bit more than I care to do for this test.
|
||||
TEST(CppPluginTest, PluginTest) {
|
||||
GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test.proto",
|
||||
"syntax = \"proto2\";\n"
|
||||
"package foo;\n"
|
||||
"\n"
|
||||
"enum Thud { VALUE = 0; }\n"
|
||||
"\n"
|
||||
"message Bar {\n"
|
||||
" message Baz {}\n"
|
||||
" optional int32 optInt = 1;\n"
|
||||
" repeated int32 repeatedInt = 2;\n"
|
||||
"\n"
|
||||
" required string requiredString = 3;\n"
|
||||
" repeated string repeatedString = 4;\n"
|
||||
"\n"
|
||||
" optional Baz optMessage = 6;\n"
|
||||
" repeated Baz repeatedMessage = 7;\n"
|
||||
"\n"
|
||||
" optional Thud optEnum = 8;\n"
|
||||
" repeated Thud repeatedEnum = 9;\n"
|
||||
"\n"
|
||||
" required string requiredCord = 10 [\n"
|
||||
" ctype = CORD\n"
|
||||
" ];\n"
|
||||
" repeated string repeatedCord = 11 [\n"
|
||||
" ctype = CORD\n"
|
||||
" ];\n"
|
||||
"\n"
|
||||
" oneof Qux {\n"
|
||||
" int64 oneOfInt = 20;\n"
|
||||
" string oneOfString = 21;\n"
|
||||
" Baz oneOfMessage = 22;\n"
|
||||
" Thud oneOfEnum = 23;"
|
||||
" string oneOfCord = 24 [\n"
|
||||
" ctype = CORD\n"
|
||||
" ];\n"
|
||||
" }\n"
|
||||
"}\n",
|
||||
true));
|
||||
|
||||
google::protobuf::compiler::CommandLineInterface cli;
|
||||
cli.SetInputsAreProtoPathRelative(true);
|
||||
|
||||
CppGenerator cpp_generator;
|
||||
TestGenerator test_generator;
|
||||
cli.RegisterGenerator("--cpp_out", &cpp_generator, "");
|
||||
cli.RegisterGenerator("--test_out", &test_generator, "");
|
||||
|
||||
string proto_path = "-I" + TestTempDir();
|
||||
string cpp_out = "--cpp_out=" + TestTempDir();
|
||||
string test_out = "--test_out=" + TestTempDir();
|
||||
|
||||
const char* argv[] = {
|
||||
"protoc",
|
||||
proto_path.c_str(),
|
||||
cpp_out.c_str(),
|
||||
test_out.c_str(),
|
||||
"test.proto"
|
||||
};
|
||||
|
||||
EXPECT_EQ(0, cli.Run(5, argv));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
+155
-64
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -80,7 +80,7 @@ int FixedSize(FieldDescriptor::Type type) {
|
||||
}
|
||||
|
||||
void SetPrimitiveVariables(const FieldDescriptor* descriptor,
|
||||
map<string, string>* variables,
|
||||
std::map<string, string>* variables,
|
||||
const Options& options) {
|
||||
SetCommonFieldVariables(descriptor, variables, options);
|
||||
(*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
|
||||
@@ -93,16 +93,16 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
|
||||
(*variables)["wire_format_field_type"] =
|
||||
"::google::protobuf::internal::WireFormatLite::" + FieldDescriptorProto_Type_Name(
|
||||
static_cast<FieldDescriptorProto_Type>(descriptor->type()));
|
||||
(*variables)["full_name"] = descriptor->full_name();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// ===================================================================
|
||||
|
||||
PrimitiveFieldGenerator::
|
||||
PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: descriptor_(descriptor) {
|
||||
PrimitiveFieldGenerator::PrimitiveFieldGenerator(
|
||||
const FieldDescriptor* descriptor, const Options& options)
|
||||
: FieldGenerator(options), descriptor_(descriptor) {
|
||||
SetPrimitiveVariables(descriptor, &variables_, options);
|
||||
}
|
||||
|
||||
@@ -116,19 +116,23 @@ 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");
|
||||
"$deprecated_attr$$type$ $name$() const;\n"
|
||||
"$deprecated_attr$void set_$name$($type$ value);\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 {
|
||||
std::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"
|
||||
" set_has_$name$();\n"
|
||||
"$inline$void $classname$::set_$name$($type$ value) {\n"
|
||||
" $set_hasbit$\n"
|
||||
" $name$_ = value;\n"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
@@ -152,13 +156,18 @@ GenerateConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_ = $default$;\n");
|
||||
}
|
||||
|
||||
void PrimitiveFieldGenerator::
|
||||
GenerateCopyConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_ = from.$name$_;\n");
|
||||
}
|
||||
|
||||
void PrimitiveFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"$set_hasbit$\n"
|
||||
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
|
||||
" $type$, $wire_format_field_type$>(\n"
|
||||
" input, &$name$_)));\n"
|
||||
"set_has_$name$();\n");
|
||||
" input, &$name$_)));\n");
|
||||
}
|
||||
|
||||
void PrimitiveFieldGenerator::
|
||||
@@ -191,13 +200,72 @@ GenerateByteSize(io::Printer* printer) const {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
RepeatedPrimitiveFieldGenerator::
|
||||
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: descriptor_(descriptor) {
|
||||
PrimitiveOneofFieldGenerator::
|
||||
PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: PrimitiveFieldGenerator(descriptor, options) {
|
||||
SetCommonOneofFieldVariables(descriptor, &variables_);
|
||||
}
|
||||
|
||||
PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
|
||||
|
||||
void PrimitiveOneofFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
|
||||
std::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"
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" }\n"
|
||||
" $oneof_prefix$$name$_ = value;\n"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void PrimitiveOneofFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n");
|
||||
}
|
||||
|
||||
void PrimitiveOneofFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
// Don't print any swapping code. Swapping the union will swap this field.
|
||||
}
|
||||
|
||||
void PrimitiveOneofFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"_$classname$_default_instance_.$name$_ = $default$;\n");
|
||||
}
|
||||
|
||||
void PrimitiveOneofFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"clear_$oneof_name$();\n"
|
||||
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
|
||||
" $type$, $wire_format_field_type$>(\n"
|
||||
" input, &$oneof_prefix$$name$_)));\n"
|
||||
"set_has_$name$();\n");
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
|
||||
const FieldDescriptor* descriptor, const Options& options)
|
||||
: FieldGenerator(options), descriptor_(descriptor) {
|
||||
SetPrimitiveVariables(descriptor, &variables_, options);
|
||||
|
||||
if (descriptor->options().packed()) {
|
||||
if (descriptor->is_packed()) {
|
||||
variables_["packed_reader"] = "ReadPackedPrimitive";
|
||||
variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
|
||||
} else {
|
||||
@@ -212,7 +280,8 @@ void RepeatedPrimitiveFieldGenerator::
|
||||
GeneratePrivateMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::RepeatedField< $type$ > $name$_;\n");
|
||||
if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) {
|
||||
if (descriptor_->is_packed() &&
|
||||
HasGeneratedMethods(descriptor_->file(), options_)) {
|
||||
printer->Print(variables_,
|
||||
"mutable int _$name$_cached_byte_size_;\n");
|
||||
}
|
||||
@@ -221,35 +290,42 @@ 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");
|
||||
"$deprecated_attr$$type$ $name$(int index) const;\n"
|
||||
"$deprecated_attr$void set_$name$(int index, $type$ value);\n"
|
||||
"$deprecated_attr$void add_$name$($type$ value);\n");
|
||||
printer->Print(variables_,
|
||||
"inline const ::google::protobuf::RepeatedField< $type$ >&\n"
|
||||
" $name$() const$deprecation$;\n"
|
||||
"inline ::google::protobuf::RepeatedField< $type$ >*\n"
|
||||
" mutable_$name$()$deprecation$;\n");
|
||||
"$deprecated_attr$const ::google::protobuf::RepeatedField< $type$ >&\n"
|
||||
" $name$() const;\n"
|
||||
"$deprecated_attr$::google::protobuf::RepeatedField< $type$ >*\n"
|
||||
" mutable_$name$();\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 {
|
||||
std::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"
|
||||
"}\n");
|
||||
}
|
||||
@@ -266,7 +342,7 @@ GenerateMergingCode(io::Printer* printer) const {
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
|
||||
printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
|
||||
}
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
@@ -274,12 +350,17 @@ GenerateConstructorCode(io::Printer* printer) const {
|
||||
// Not needed for repeated fields.
|
||||
}
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GenerateCopyConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.CopyFrom(from.$name$_);\n");
|
||||
}
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"DO_((::google::protobuf::internal::WireFormatLite::$repeated_reader$<\n"
|
||||
" $type$, $wire_format_field_type$>(\n"
|
||||
" $tag_size$, $tag$, input, this->mutable_$name$())));\n");
|
||||
" $tag_size$, $tag$u, input, this->mutable_$name$())));\n");
|
||||
}
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
@@ -292,7 +373,8 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
if (descriptor_->options().packed()) {
|
||||
bool array_written = false;
|
||||
if (descriptor_->is_packed()) {
|
||||
// Write the tag and the size.
|
||||
printer->Print(variables_,
|
||||
"if (this->$name$_size() > 0) {\n"
|
||||
@@ -300,26 +382,35 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
"$number$, "
|
||||
"::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, "
|
||||
"output);\n"
|
||||
" output->WriteVarint32(_$name$_cached_byte_size_);\n"
|
||||
"}\n");
|
||||
" output->WriteVarint32(_$name$_cached_byte_size_);\n");
|
||||
|
||||
if (FixedSize(descriptor_->type()) > 0) {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$Array(\n"
|
||||
" this->$name$().data(), this->$name$_size(), output);\n");
|
||||
array_written = true; // Wrote array all at once
|
||||
}
|
||||
printer->Print(variables_, "}\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||
if (descriptor_->options().packed()) {
|
||||
if (!array_written) {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n"
|
||||
" this->$name$(i), output);\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
|
||||
" $number$, this->$name$(i), output);\n");
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||
if (descriptor_->is_packed()) {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n"
|
||||
" this->$name$(i), output);\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
|
||||
" $number$, this->$name$(i), output);\n");
|
||||
}
|
||||
printer->Print("}\n");
|
||||
}
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
if (descriptor_->options().packed()) {
|
||||
if (descriptor_->is_packed()) {
|
||||
// Write the tag and the size.
|
||||
printer->Print(variables_,
|
||||
"if (this->$name$_size() > 0) {\n"
|
||||
@@ -333,7 +424,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||
if (descriptor_->options().packed()) {
|
||||
if (descriptor_->is_packed()) {
|
||||
printer->Print(variables_,
|
||||
" target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" Write$declared_type$NoTagToArray(this->$name$(i), target);\n");
|
||||
@@ -347,35 +438,35 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"{\n"
|
||||
" int data_size = 0;\n");
|
||||
printer->Print(variables_, "{\n");
|
||||
printer->Indent();
|
||||
int fixed_size = FixedSize(descriptor_->type());
|
||||
if (fixed_size == -1) {
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||
" data_size += ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" $declared_type$Size(this->$name$(i));\n"
|
||||
"}\n");
|
||||
"size_t data_size = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" $declared_type$Size(this->$name$_);\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"data_size = $fixed_size$ * this->$name$_size();\n");
|
||||
"unsigned int count = this->$name$_size();\n"
|
||||
"size_t data_size = $fixed_size$UL * count;\n");
|
||||
}
|
||||
|
||||
if (descriptor_->options().packed()) {
|
||||
if (descriptor_->is_packed()) {
|
||||
printer->Print(variables_,
|
||||
"if (data_size > 0) {\n"
|
||||
" total_size += $tag_size$ +\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
|
||||
"}\n"
|
||||
"int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);\n"
|
||||
"GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
|
||||
"_$name$_cached_byte_size_ = data_size;\n"
|
||||
"_$name$_cached_byte_size_ = cached_size;\n"
|
||||
"GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
|
||||
"total_size += data_size;\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ * this->$name$_size() + data_size;\n");
|
||||
"total_size += $tag_size$ *\n"
|
||||
" ::google::protobuf::internal::FromIntSize(this->$name$_size());\n"
|
||||
"total_size += data_size;\n");
|
||||
}
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
+33
-10
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -46,44 +46,67 @@ namespace cpp {
|
||||
|
||||
class PrimitiveFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~PrimitiveFieldGenerator();
|
||||
|
||||
// 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;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
protected:
|
||||
const FieldDescriptor* descriptor_;
|
||||
map<string, string> variables_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
|
||||
};
|
||||
|
||||
class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
|
||||
public:
|
||||
PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~PrimitiveOneofFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
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;
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator);
|
||||
};
|
||||
|
||||
class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~RepeatedPrimitiveFieldGenerator();
|
||||
|
||||
// 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;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||
@@ -92,7 +115,7 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
|
||||
|
||||
private:
|
||||
const FieldDescriptor* descriptor_;
|
||||
map<string, string> variables_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
|
||||
};
|
||||
+37
-31
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -46,6 +46,7 @@ ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: descriptor_(descriptor) {
|
||||
vars_["classname"] = descriptor_->name();
|
||||
vars_["file_namespace"] = FileLevelNamespace(descriptor_->file()->name());
|
||||
vars_["full_name"] = descriptor_->full_name();
|
||||
if (options.dllexport_decl.empty()) {
|
||||
vars_["dllexport"] = "";
|
||||
@@ -143,7 +144,7 @@ void ServiceGenerator::GenerateMethodSignatures(
|
||||
VirtualOrNon virtual_or_non, io::Printer* printer) {
|
||||
for (int i = 0; i < descriptor_->method_count(); i++) {
|
||||
const MethodDescriptor* method = descriptor_->method(i);
|
||||
map<string, string> sub_vars;
|
||||
std::map<string, string> sub_vars;
|
||||
sub_vars["name"] = method->name();
|
||||
sub_vars["input_type"] = ClassName(method->input_type(), true);
|
||||
sub_vars["output_type"] = ClassName(method->output_type(), true);
|
||||
@@ -161,7 +162,7 @@ void ServiceGenerator::GenerateMethodSignatures(
|
||||
|
||||
void ServiceGenerator::GenerateDescriptorInitializer(
|
||||
io::Printer* printer, int index) {
|
||||
map<string, string> vars;
|
||||
std::map<string, string> vars;
|
||||
vars["classname"] = descriptor_->name();
|
||||
vars["index"] = SimpleItoa(index);
|
||||
|
||||
@@ -172,19 +173,20 @@ void ServiceGenerator::GenerateDescriptorInitializer(
|
||||
// ===================================================================
|
||||
|
||||
void ServiceGenerator::GenerateImplementation(io::Printer* printer) {
|
||||
printer->Print(vars_,
|
||||
"$classname$::~$classname$() {}\n"
|
||||
"\n"
|
||||
"const ::google::protobuf::ServiceDescriptor* $classname$::descriptor() {\n"
|
||||
" protobuf_AssignDescriptorsOnce();\n"
|
||||
" return $classname$_descriptor_;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"const ::google::protobuf::ServiceDescriptor* $classname$::GetDescriptor() {\n"
|
||||
" protobuf_AssignDescriptorsOnce();\n"
|
||||
" return $classname$_descriptor_;\n"
|
||||
"}\n"
|
||||
"\n");
|
||||
vars_["index"] = SimpleItoa(index_in_metadata_);
|
||||
printer->Print(
|
||||
vars_,
|
||||
"$classname$::~$classname$() {}\n"
|
||||
"\n"
|
||||
"const ::google::protobuf::ServiceDescriptor* $classname$::descriptor() {\n"
|
||||
" $file_namespace$::protobuf_AssignDescriptorsOnce();\n"
|
||||
" return $file_namespace$::file_level_service_descriptors[$index$];\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"const ::google::protobuf::ServiceDescriptor* $classname$::GetDescriptor() {\n"
|
||||
" return descriptor();\n"
|
||||
"}\n"
|
||||
"\n");
|
||||
|
||||
// Generate methods of the interface.
|
||||
GenerateNotImplementedMethods(printer);
|
||||
@@ -212,7 +214,7 @@ void ServiceGenerator::GenerateImplementation(io::Printer* printer) {
|
||||
void ServiceGenerator::GenerateNotImplementedMethods(io::Printer* printer) {
|
||||
for (int i = 0; i < descriptor_->method_count(); i++) {
|
||||
const MethodDescriptor* method = descriptor_->method(i);
|
||||
map<string, string> sub_vars;
|
||||
std::map<string, string> sub_vars;
|
||||
sub_vars["classname"] = descriptor_->name();
|
||||
sub_vars["name"] = method->name();
|
||||
sub_vars["index"] = SimpleItoa(i);
|
||||
@@ -232,18 +234,20 @@ void ServiceGenerator::GenerateNotImplementedMethods(io::Printer* printer) {
|
||||
}
|
||||
|
||||
void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
|
||||
printer->Print(vars_,
|
||||
"void $classname$::CallMethod(const ::google::protobuf::MethodDescriptor* method,\n"
|
||||
" ::google::protobuf::RpcController* controller,\n"
|
||||
" const ::google::protobuf::Message* request,\n"
|
||||
" ::google::protobuf::Message* response,\n"
|
||||
" ::google::protobuf::Closure* done) {\n"
|
||||
" GOOGLE_DCHECK_EQ(method->service(), $classname$_descriptor_);\n"
|
||||
" switch(method->index()) {\n");
|
||||
printer->Print(
|
||||
vars_,
|
||||
"void $classname$::CallMethod(const ::google::protobuf::MethodDescriptor* method,\n"
|
||||
" ::google::protobuf::RpcController* controller,\n"
|
||||
" const ::google::protobuf::Message* request,\n"
|
||||
" ::google::protobuf::Message* response,\n"
|
||||
" ::google::protobuf::Closure* done) {\n"
|
||||
" GOOGLE_DCHECK_EQ(method->service(), "
|
||||
"$file_namespace$::file_level_service_descriptors[$index$]);\n"
|
||||
" switch(method->index()) {\n");
|
||||
|
||||
for (int i = 0; i < descriptor_->method_count(); i++) {
|
||||
const MethodDescriptor* method = descriptor_->method(i);
|
||||
map<string, string> sub_vars;
|
||||
std::map<string, string> sub_vars;
|
||||
sub_vars["name"] = method->name();
|
||||
sub_vars["index"] = SimpleItoa(i);
|
||||
sub_vars["input_type"] = ClassName(method->input_type(), true);
|
||||
@@ -289,7 +293,7 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
|
||||
const Descriptor* type =
|
||||
(which == REQUEST) ? method->input_type() : method->output_type();
|
||||
|
||||
map<string, string> sub_vars;
|
||||
std::map<string, string> sub_vars;
|
||||
sub_vars["index"] = SimpleItoa(i);
|
||||
sub_vars["type"] = ClassName(type, true);
|
||||
|
||||
@@ -298,19 +302,21 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
|
||||
" return $type$::default_instance();\n");
|
||||
}
|
||||
|
||||
printer->Print(vars_,
|
||||
printer->Print(
|
||||
" default:\n"
|
||||
" GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n"
|
||||
" return *reinterpret_cast< ::google::protobuf::Message*>(NULL);\n"
|
||||
" return *::google::protobuf::MessageFactory::generated_factory()\n"
|
||||
" ->GetPrototype(method->$input_or_output$_type());\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n");
|
||||
"\n",
|
||||
"input_or_output", which == REQUEST ? "input" : "output");
|
||||
}
|
||||
|
||||
void ServiceGenerator::GenerateStubMethods(io::Printer* printer) {
|
||||
for (int i = 0; i < descriptor_->method_count(); i++) {
|
||||
const MethodDescriptor* method = descriptor_->method(i);
|
||||
map<string, string> sub_vars;
|
||||
std::map<string, string> sub_vars;
|
||||
sub_vars["classname"] = descriptor_->name();
|
||||
sub_vars["name"] = method->name();
|
||||
sub_vars["index"] = SimpleItoa(i);
|
||||
+5
-3
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -37,7 +37,6 @@
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_options.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
@@ -106,8 +105,11 @@ class ServiceGenerator {
|
||||
void GenerateStubMethods(io::Printer* printer);
|
||||
|
||||
const ServiceDescriptor* descriptor_;
|
||||
map<string, string> vars_;
|
||||
std::map<string, string> vars_;
|
||||
|
||||
int index_in_metadata_;
|
||||
|
||||
friend class FileGenerator;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,999 @@
|
||||
// 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.
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_string_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_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 cpp {
|
||||
|
||||
namespace {
|
||||
|
||||
void SetStringVariables(const FieldDescriptor* descriptor,
|
||||
std::map<string, string>* variables,
|
||||
const Options& options) {
|
||||
SetCommonFieldVariables(descriptor, variables, options);
|
||||
(*variables)["default"] = DefaultValue(descriptor);
|
||||
(*variables)["default_length"] =
|
||||
SimpleItoa(descriptor->default_value_string().length());
|
||||
string default_variable_string = "_default_" + FieldName(descriptor) + "_";
|
||||
(*variables)["default_variable_name"] = default_variable_string;
|
||||
(*variables)["default_variable"] =
|
||||
descriptor->default_value_string().empty()
|
||||
? "&::google::protobuf::internal::GetEmptyStringAlreadyInited()"
|
||||
: "&" + (*variables)["classname"] + "::" + default_variable_string +
|
||||
".get()";
|
||||
(*variables)["pointer_type"] =
|
||||
descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
|
||||
// NOTE: Escaped here to unblock proto1->proto2 migration.
|
||||
// TODO(liujisi): Extend this to apply for other conflicting methods.
|
||||
(*variables)["release_name"] =
|
||||
SafeFunctionName(descriptor->containing_type(),
|
||||
descriptor, "release_");
|
||||
(*variables)["full_name"] = descriptor->full_name();
|
||||
|
||||
(*variables)["string_piece"] = "::std::string";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// ===================================================================
|
||||
|
||||
StringFieldGenerator::StringFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: FieldGenerator(options), descriptor_(descriptor) {
|
||||
SetStringVariables(descriptor, &variables_, options);
|
||||
}
|
||||
|
||||
StringFieldGenerator::~StringFieldGenerator() {}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GeneratePrivateMembers(io::Printer* printer) const {
|
||||
// N.B. that we continue to use |ArenaStringPtr| instead of |string*| for
|
||||
// string fields, even when SupportArenas(descriptor_) == false. Why?
|
||||
// The simple answer is to avoid unmaintainable complexity. The reflection
|
||||
// code assumes ArenaStringPtrs. These are *almost* in-memory-compatible with
|
||||
// string*, except for the pointer tags and related ownership semantics. We
|
||||
// could modify the runtime code to use string* for the not-supporting-arenas
|
||||
// case, but this would require a way to detect which type of class was
|
||||
// generated (adding overhead and complexity to GeneratedMessageReflection)
|
||||
// and littering the runtime code paths with conditionals. It's simpler to
|
||||
// stick with this but use lightweight accessors that assume arena == NULL.
|
||||
// There should be very little overhead anyway because it's just a tagged
|
||||
// pointer in-memory.
|
||||
printer->Print(variables_, "::google::protobuf::internal::ArenaStringPtr $name$_;\n");
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateStaticMembers(io::Printer* printer) const {
|
||||
if (!descriptor_->default_value_string().empty()) {
|
||||
printer->Print(variables_,
|
||||
"static ::google::protobuf::internal::ExplicitlyConstructed< ::std::string>"
|
||||
" $default_variable_name$;\n");
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
// If we're using StringFieldGenerator for a field with a ctype, it's
|
||||
// because that ctype isn't actually implemented. In particular, this is
|
||||
// true of ctype=CORD and ctype=STRING_PIECE in the open source release.
|
||||
// We aren't releasing Cord because it has too many Google-specific
|
||||
// dependencies and we aren't releasing StringPiece because it's hardly
|
||||
// useful outside of Google and because it would get confusing to have
|
||||
// multiple instances of the StringPiece class in different libraries (PCRE
|
||||
// already includes it for their C++ bindings, which came from Google).
|
||||
//
|
||||
// In any case, we make all the accessors private while still actually
|
||||
// using a string to represent the field internally. This way, we can
|
||||
// guarantee that if we do ever implement the ctype, it won't break any
|
||||
// existing users who might be -- for whatever reason -- already using .proto
|
||||
// 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.
|
||||
|
||||
bool unknown_ctype =
|
||||
descriptor_->options().ctype() != EffectiveStringCType(descriptor_);
|
||||
|
||||
if (unknown_ctype) {
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
" private:\n"
|
||||
" // Hidden due to unknown ctype option.\n");
|
||||
printer->Indent();
|
||||
}
|
||||
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$const ::std::string& $name$() const;\n"
|
||||
"$deprecated_attr$void set_$name$(const ::std::string& value);\n");
|
||||
|
||||
if (!SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables_,
|
||||
"#if LANG_CXX11\n"
|
||||
"$deprecated_attr$void set_$name$(::std::string&& value);\n"
|
||||
"#endif\n");
|
||||
}
|
||||
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$void set_$name$(const char* value);\n"
|
||||
"$deprecated_attr$void set_$name$(const $pointer_type$* value, size_t size)"
|
||||
";\n"
|
||||
"$deprecated_attr$::std::string* mutable_$name$();\n"
|
||||
"$deprecated_attr$::std::string* $release_name$();\n"
|
||||
"$deprecated_attr$void set_allocated_$name$(::std::string* $name$);\n");
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$::std::string* unsafe_arena_release_$name$();\n"
|
||||
"$deprecated_attr$void unsafe_arena_set_allocated_$name$(\n"
|
||||
" ::std::string* $name$);\n");
|
||||
}
|
||||
|
||||
|
||||
if (unknown_ctype) {
|
||||
printer->Outdent();
|
||||
printer->Print(" public:\n");
|
||||
printer->Indent();
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer,
|
||||
bool is_inline) const {
|
||||
std::map<string, string> variables(variables_);
|
||||
variables["inline"] = is_inline ? "inline " : "";
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(
|
||||
variables,
|
||||
"$inline$const ::std::string& $classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" return $name$_.Get();\n"
|
||||
"}\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"
|
||||
" $set_hasbit$\n"
|
||||
" $name$_.Set($default_variable$, $string_piece$(value),\n"
|
||||
" GetArenaNoVirtual());\n"
|
||||
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
|
||||
"}\n"
|
||||
"$inline$"
|
||||
"void $classname$::set_$name$(const $pointer_type$* value,\n"
|
||||
" size_t size) {\n"
|
||||
" $set_hasbit$\n"
|
||||
" $name$_.Set($default_variable$, $string_piece$(\n"
|
||||
" 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"
|
||||
" $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"
|
||||
" // @@protoc_insertion_point(field_release:$full_name$)\n"
|
||||
" $clear_hasbit$\n"
|
||||
" return $name$_.Release($default_variable$, GetArenaNoVirtual());\n"
|
||||
"}\n"
|
||||
"$inline$::std::string* $classname$::unsafe_arena_release_$name$() {\n"
|
||||
" // "
|
||||
"@@protoc_insertion_point(field_unsafe_arena_release:$full_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"
|
||||
" if ($name$ != NULL) {\n"
|
||||
" $set_hasbit$\n"
|
||||
" } else {\n"
|
||||
" $clear_hasbit$\n"
|
||||
" }\n"
|
||||
" $name$_.SetAllocated($default_variable$, $name$,\n"
|
||||
" GetArenaNoVirtual());\n"
|
||||
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
|
||||
"}\n"
|
||||
"$inline$void $classname$::unsafe_arena_set_allocated_$name$(\n"
|
||||
" ::std::string* $name$) {\n"
|
||||
" GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
|
||||
" if ($name$ != NULL) {\n"
|
||||
" $set_hasbit$\n"
|
||||
" } else {\n"
|
||||
" $clear_hasbit$\n"
|
||||
" }\n"
|
||||
" $name$_.UnsafeArenaSetAllocated($default_variable$,\n"
|
||||
" $name$, GetArenaNoVirtual());\n"
|
||||
" // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
|
||||
"$full_name$)\n"
|
||||
"}\n");
|
||||
} else {
|
||||
// No-arena case.
|
||||
printer->Print(
|
||||
variables,
|
||||
"$inline$const ::std::string& $classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" return $name$_.GetNoArena();\n"
|
||||
"}\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"
|
||||
"#if LANG_CXX11\n"
|
||||
"$inline$void $classname$::set_$name$(::std::string&& value) {\n"
|
||||
" $set_hasbit$\n"
|
||||
" $name$_.SetNoArena(\n"
|
||||
" $default_variable$, std::move(value));\n"
|
||||
" // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
|
||||
"}\n"
|
||||
"#endif\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$"
|
||||
"void $classname$::set_$name$(const $pointer_type$* value, "
|
||||
"size_t size) {\n"
|
||||
" $set_hasbit$\n"
|
||||
" $name$_.SetNoArena($default_variable$,\n"
|
||||
" $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"
|
||||
" $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"
|
||||
" // @@protoc_insertion_point(field_release:$full_name$)\n"
|
||||
" $clear_hasbit$\n"
|
||||
" return $name$_.ReleaseNoArena($default_variable$);\n"
|
||||
"}\n"
|
||||
"$inline$void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
|
||||
" if ($name$ != NULL) {\n"
|
||||
" $set_hasbit$\n"
|
||||
" } else {\n"
|
||||
" $clear_hasbit$\n"
|
||||
" }\n"
|
||||
" $name$_.SetAllocatedNoArena($default_variable$, $name$);\n"
|
||||
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
if (!descriptor_->default_value_string().empty()) {
|
||||
// Initialized in GenerateDefaultInstanceAllocator.
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::ExplicitlyConstructed< ::std::string> "
|
||||
"$classname$::$default_variable_name$;\n");
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
// Two-dimension specialization here: supporting arenas or not, and default
|
||||
// value is the empty string or not. Complexity here ensures the minimal
|
||||
// number of branches / amount of extraneous code at runtime (given that the
|
||||
// below methods are inlined one-liners)!
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
if (descriptor_->default_value_string().empty()) {
|
||||
printer->Print(variables_,
|
||||
"$name$_.ClearToEmpty($default_variable$, GetArenaNoVirtual());\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"$name$_.ClearToDefault($default_variable$, GetArenaNoVirtual());\n");
|
||||
}
|
||||
} else {
|
||||
if (descriptor_->default_value_string().empty()) {
|
||||
printer->Print(variables_,
|
||||
"$name$_.ClearToEmptyNoArena($default_variable$);\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"$name$_.ClearToDefaultNoArena($default_variable$);\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateMessageClearingCode(io::Printer* printer) const {
|
||||
// Two-dimension specialization here: supporting arenas, field presence, or
|
||||
// not, and default value is the empty string or not. Complexity here ensures
|
||||
// the minimal number of branches / amount of extraneous code at runtime
|
||||
// (given that the below methods are inlined one-liners)!
|
||||
|
||||
// If we have field presence, then the Clear() method of the protocol buffer
|
||||
// will have checked that this field is set. If so, we can avoid redundant
|
||||
// checks against default_variable.
|
||||
const bool must_be_present = HasFieldPresence(descriptor_->file());
|
||||
|
||||
if (must_be_present) {
|
||||
printer->Print(variables_,
|
||||
"GOOGLE_DCHECK(!$name$_.IsDefault($default_variable$));\n");
|
||||
}
|
||||
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
if (descriptor_->default_value_string().empty()) {
|
||||
printer->Print(variables_,
|
||||
"$name$_.ClearToEmpty($default_variable$, GetArenaNoVirtual());\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"$name$_.ClearToDefault($default_variable$, GetArenaNoVirtual());\n");
|
||||
}
|
||||
} else if (must_be_present) {
|
||||
// When Arenas are disabled and field presence has been checked, we can
|
||||
// safely treat the ArenaStringPtr as a string*.
|
||||
if (descriptor_->default_value_string().empty()) {
|
||||
printer->Print(variables_,
|
||||
"(*$name$_.UnsafeRawStringPointer())->clear();\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"(*$name$_.UnsafeRawStringPointer())->assign(*$default_variable$);\n");
|
||||
}
|
||||
} else {
|
||||
if (descriptor_->default_value_string().empty()) {
|
||||
printer->Print(variables_,
|
||||
"$name$_.ClearToEmptyNoArena($default_variable$);\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"$name$_.ClearToDefaultNoArena($default_variable$);\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateMergingCode(io::Printer* printer) const {
|
||||
if (SupportsArenas(descriptor_) || descriptor_->containing_oneof() != NULL) {
|
||||
// TODO(gpike): improve this
|
||||
printer->Print(variables_, "set_$name$(from.$name$());\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"$set_hasbit$\n"
|
||||
"$name$_.AssignWithDefault($default_variable$, from.$name$_);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"$name$_.UnsafeSetDefault($default_variable$);\n");
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateCopyConstructorCode(io::Printer* printer) const {
|
||||
GenerateConstructorCode(printer);
|
||||
|
||||
if (HasFieldPresence(descriptor_->file())) {
|
||||
printer->Print(variables_,
|
||||
"if (from.has_$name$()) {\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"if (from.$name$().size() > 0) {\n");
|
||||
}
|
||||
|
||||
printer->Indent();
|
||||
|
||||
if (SupportsArenas(descriptor_) || descriptor_->containing_oneof() != NULL) {
|
||||
// TODO(gpike): improve this
|
||||
printer->Print(variables_,
|
||||
"$name$_.Set($default_variable$, from.$name$(),\n"
|
||||
" GetArenaNoVirtual());\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"$name$_.AssignWithDefault($default_variable$, from.$name$_);\n");
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateDestructorCode(io::Printer* printer) const {
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
// The variable |arena| is defined by the enclosing code.
|
||||
// See MessageGenerator::GenerateSharedDestructorCode.
|
||||
printer->Print(variables_,
|
||||
"$name$_.Destroy($default_variable$, arena);\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"$name$_.DestroyNoArena($default_variable$);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateDefaultInstanceAllocator(io::Printer* printer) const {
|
||||
if (!descriptor_->default_value_string().empty()) {
|
||||
printer->Print(variables_,
|
||||
"$classname$::$default_variable_name$.DefaultConstruct();\n"
|
||||
"*$classname$::$default_variable_name$.get_mutable() = "
|
||||
"::std::string($default$, $default_length$);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateShutdownCode(io::Printer* printer) const {
|
||||
if (!descriptor_->default_value_string().empty()) {
|
||||
printer->Print(variables_,
|
||||
"$classname$::$default_variable_name$.Shutdown();\n");
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
|
||||
" input, this->mutable_$name$()));\n");
|
||||
|
||||
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
GenerateUtf8CheckCodeForString(
|
||||
descriptor_, options_, true, variables_,
|
||||
"this->$name$().data(), this->$name$().length(),\n", printer);
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
GenerateUtf8CheckCodeForString(
|
||||
descriptor_, options_, false, variables_,
|
||||
"this->$name$().data(), this->$name$().length(),\n", printer);
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormatLite::Write$declared_type$MaybeAliased(\n"
|
||||
" $number$, this->$name$(), output);\n");
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
GenerateUtf8CheckCodeForString(
|
||||
descriptor_, options_, false, variables_,
|
||||
"this->$name$().data(), this->$name$().length(),\n", printer);
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"target =\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(\n"
|
||||
" $number$, this->$name$(), target);\n");
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ +\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
|
||||
" this->$name$());\n");
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
StringOneofFieldGenerator::
|
||||
StringOneofFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: StringFieldGenerator(descriptor, options),
|
||||
dependent_field_(options.proto_h) {
|
||||
SetCommonOneofFieldVariables(descriptor, &variables_);
|
||||
}
|
||||
|
||||
StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
|
||||
|
||||
void StringOneofFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer,
|
||||
bool is_inline) const {
|
||||
std::map<string, string> variables(variables_);
|
||||
variables["inline"] = is_inline ? "inline " : "";
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
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();\n"
|
||||
" }\n"
|
||||
" return *$default_variable$;\n"
|
||||
"}\n"
|
||||
"$inline$void $classname$::set_$name$(const ::std::string& value) {\n"
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" $oneof_prefix$$name$_.Set($default_variable$, value,\n"
|
||||
" GetArenaNoVirtual());\n"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
"}\n"
|
||||
"$inline$void $classname$::set_$name$(const char* value) {\n"
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" $oneof_prefix$$name$_.Set($default_variable$,\n"
|
||||
" $string_piece$(value), GetArenaNoVirtual());\n"
|
||||
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
|
||||
"}\n"
|
||||
"$inline$"
|
||||
"void $classname$::set_$name$(const $pointer_type$* value,\n"
|
||||
" size_t size) {\n"
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" $oneof_prefix$$name$_.Set($default_variable$, $string_piece$(\n"
|
||||
" reinterpret_cast<const char*>(value), size),\n"
|
||||
" GetArenaNoVirtual());\n"
|
||||
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
|
||||
"}\n"
|
||||
"$inline$::std::string* $classname$::mutable_$name$() {\n"
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" return $oneof_prefix$$name$_.Mutable($default_variable$,\n"
|
||||
" GetArenaNoVirtual());\n"
|
||||
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
||||
"}\n"
|
||||
"$inline$::std::string* $classname$::$release_name$() {\n"
|
||||
" // @@protoc_insertion_point(field_release:$full_name$)\n"
|
||||
" if (has_$name$()) {\n"
|
||||
" clear_has_$oneof_name$();\n"
|
||||
" return $oneof_prefix$$name$_.Release($default_variable$,\n"
|
||||
" GetArenaNoVirtual());\n"
|
||||
" } else {\n"
|
||||
" return NULL;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"$inline$::std::string* $classname$::unsafe_arena_release_$name$() {\n"
|
||||
" // "
|
||||
"@@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
|
||||
" GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
|
||||
" if (has_$name$()) {\n"
|
||||
" clear_has_$oneof_name$();\n"
|
||||
" return $oneof_prefix$$name$_.UnsafeArenaRelease(\n"
|
||||
" $default_variable$, GetArenaNoVirtual());\n"
|
||||
" } else {\n"
|
||||
" return NULL;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"$inline$void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
|
||||
" if (!has_$name$()) {\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" if ($name$ != NULL) {\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.SetAllocated($default_variable$, $name$,\n"
|
||||
" GetArenaNoVirtual());\n"
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
|
||||
"}\n"
|
||||
"$inline$void $classname$::unsafe_arena_set_allocated_$name$("
|
||||
"::std::string* $name$) {\n"
|
||||
" GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
|
||||
" if (!has_$name$()) {\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" if ($name$) {\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeArenaSetAllocated($default_variable$, "
|
||||
"$name$, GetArenaNoVirtual());\n"
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
|
||||
"$full_name$)\n"
|
||||
"}\n");
|
||||
} else {
|
||||
// No-arena case.
|
||||
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();\n"
|
||||
" }\n"
|
||||
" return *$default_variable$;\n"
|
||||
"}\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"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" $oneof_prefix$$name$_.SetNoArena($default_variable$, value);\n"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
"}\n"
|
||||
"#if LANG_CXX11\n"
|
||||
"$inline$void $classname$::set_$name$(::std::string&& value) {\n"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" $oneof_prefix$$name$_.SetNoArena(\n"
|
||||
" $default_variable$, std::move(value));\n"
|
||||
" // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
|
||||
"}\n"
|
||||
"#endif\n"
|
||||
"$inline$void $classname$::set_$name$(const char* value) {\n"
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" $oneof_prefix$$name$_.SetNoArena($default_variable$,\n"
|
||||
" $string_piece$(value));\n"
|
||||
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
|
||||
"}\n"
|
||||
"$inline$"
|
||||
"void $classname$::set_$name$(const $pointer_type$* value, size_t "
|
||||
"size) {\n"
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" $oneof_prefix$$name$_.SetNoArena($default_variable$, "
|
||||
"$string_piece$(\n"
|
||||
" reinterpret_cast<const char*>(value), size));\n"
|
||||
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
|
||||
"}\n"
|
||||
"$inline$::std::string* $classname$::mutable_$name$() {\n"
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
||||
" return $oneof_prefix$$name$_.MutableNoArena($default_variable$);\n"
|
||||
"}\n"
|
||||
"$inline$::std::string* $classname$::$release_name$() {\n"
|
||||
" // @@protoc_insertion_point(field_release:$full_name$)\n"
|
||||
" if (has_$name$()) {\n"
|
||||
" clear_has_$oneof_name$();\n"
|
||||
" return $oneof_prefix$$name$_.ReleaseNoArena($default_variable$);\n"
|
||||
" } else {\n"
|
||||
" return NULL;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"$inline$void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
|
||||
" if (!has_$name$()) {\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" if ($name$ != NULL) {\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.SetAllocatedNoArena($default_variable$,\n"
|
||||
" $name$);\n"
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void StringOneofFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
std::map<string, string> variables(variables_);
|
||||
if (dependent_field_) {
|
||||
variables["this_message"] = DependentBaseDownCast();
|
||||
// This clearing code may be in the dependent base class. If the default
|
||||
// value is an empty string, then the $default_variable$ is a global
|
||||
// singleton. If the default is not empty, we need to down-cast to get the
|
||||
// default value's global singleton instance. See SetStringVariables() for
|
||||
// possible values of default_variable.
|
||||
if (!descriptor_->default_value_string().empty()) {
|
||||
variables["default_variable"] = "&" + DependentBaseDownCast() +
|
||||
variables["default_variable_name"] +
|
||||
".get()";
|
||||
}
|
||||
} else {
|
||||
variables["this_message"] = "";
|
||||
}
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables,
|
||||
"$this_message$$oneof_prefix$$name$_.Destroy($default_variable$,\n"
|
||||
" $this_message$GetArenaNoVirtual());\n");
|
||||
} else {
|
||||
printer->Print(variables,
|
||||
"$this_message$$oneof_prefix$$name$_."
|
||||
"DestroyNoArena($default_variable$);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void StringOneofFieldGenerator::
|
||||
GenerateMessageClearingCode(io::Printer* printer) const {
|
||||
return GenerateClearingCode(printer);
|
||||
}
|
||||
|
||||
void StringOneofFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
// Don't print any swapping code. Swapping the union will swap this field.
|
||||
}
|
||||
|
||||
void StringOneofFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"_$classname$_default_instance_.$name$_.UnsafeSetDefault(\n"
|
||||
" $default_variable$);\n");
|
||||
}
|
||||
|
||||
void StringOneofFieldGenerator::
|
||||
GenerateDestructorCode(io::Printer* printer) const {
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables_,
|
||||
"if (has_$name$()) {\n"
|
||||
" $oneof_prefix$$name$_.Destroy($default_variable$,\n"
|
||||
" GetArenaNoVirtual());\n"
|
||||
"}\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"if (has_$name$()) {\n"
|
||||
" $oneof_prefix$$name$_.DestroyNoArena($default_variable$);\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void StringOneofFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
|
||||
" input, this->mutable_$name$()));\n");
|
||||
|
||||
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
GenerateUtf8CheckCodeForString(
|
||||
descriptor_, options_, true, variables_,
|
||||
"this->$name$().data(), this->$name$().length(),\n", printer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
RepeatedStringFieldGenerator::RepeatedStringFieldGenerator(
|
||||
const FieldDescriptor* descriptor, const Options& options)
|
||||
: FieldGenerator(options), descriptor_(descriptor) {
|
||||
SetStringVariables(descriptor, &variables_, options);
|
||||
}
|
||||
|
||||
RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GeneratePrivateMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::RepeatedPtrField< ::std::string> $name$_;\n");
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
// See comment above about unknown ctypes.
|
||||
bool unknown_ctype =
|
||||
descriptor_->options().ctype() != EffectiveStringCType(descriptor_);
|
||||
|
||||
if (unknown_ctype) {
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
" private:\n"
|
||||
" // Hidden due to unknown ctype option.\n");
|
||||
printer->Indent();
|
||||
}
|
||||
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$const ::std::string& $name$(int index) const;\n"
|
||||
"$deprecated_attr$::std::string* mutable_$name$(int index);\n"
|
||||
"$deprecated_attr$void set_$name$(int index, const ::std::string& value);\n"
|
||||
"$deprecated_attr$void set_$name$(int index, const char* value);\n"
|
||||
""
|
||||
"$deprecated_attr$void set_$name$("
|
||||
"int index, const $pointer_type$* value, size_t size);\n"
|
||||
"$deprecated_attr$::std::string* add_$name$();\n"
|
||||
"$deprecated_attr$void add_$name$(const ::std::string& value);\n"
|
||||
"$deprecated_attr$void add_$name$(const char* value);\n"
|
||||
"$deprecated_attr$void add_$name$(const $pointer_type$* value, size_t size)"
|
||||
";\n"
|
||||
"$deprecated_attr$const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() "
|
||||
"const;\n"
|
||||
"$deprecated_attr$::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
|
||||
";\n");
|
||||
|
||||
if (unknown_ctype) {
|
||||
printer->Outdent();
|
||||
printer->Print(" public:\n");
|
||||
printer->Indent();
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer,
|
||||
bool is_inline) const {
|
||||
std::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"
|
||||
" // @@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"
|
||||
" // @@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"
|
||||
" $name$_.Mutable(index)->assign(value);\n"
|
||||
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
|
||||
"}\n"
|
||||
"$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"
|
||||
" // @@protoc_insertion_point(field_add_mutable:$full_name$)\n"
|
||||
" return $name$_.Add();\n"
|
||||
"}\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"
|
||||
" $name$_.Add()->assign(value);\n"
|
||||
" // @@protoc_insertion_point(field_add_char:$full_name$)\n"
|
||||
"}\n"
|
||||
"$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"
|
||||
"$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"
|
||||
"$classname$::mutable_$name$() {\n"
|
||||
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
|
||||
" return &$name$_;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.Clear();\n");
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateMergingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
// Not needed for repeated fields.
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateCopyConstructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.CopyFrom(from.$name$_);");
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
|
||||
" input, this->add_$name$()));\n");
|
||||
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
GenerateUtf8CheckCodeForString(
|
||||
descriptor_, options_, true, variables_,
|
||||
"this->$name$(this->$name$_size() - 1).data(),\n"
|
||||
"this->$name$(this->$name$_size() - 1).length(),\n",
|
||||
printer);
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||
printer->Indent();
|
||||
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
GenerateUtf8CheckCodeForString(
|
||||
descriptor_, options_, false, variables_,
|
||||
"this->$name$(i).data(), this->$name$(i).length(),\n", printer);
|
||||
}
|
||||
printer->Outdent();
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
|
||||
" $number$, this->$name$(i), output);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||
printer->Indent();
|
||||
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
GenerateUtf8CheckCodeForString(
|
||||
descriptor_, options_, false, variables_,
|
||||
"this->$name$(i).data(), this->$name$(i).length(),\n", printer);
|
||||
}
|
||||
printer->Outdent();
|
||||
printer->Print(variables_,
|
||||
" target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" Write$declared_type$ToArray($number$, this->$name$(i), target);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ *\n"
|
||||
" ::google::protobuf::internal::FromIntSize(this->$name$_size());\n"
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||
" total_size += ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
|
||||
" this->$name$(i));\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
+41
-10
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -46,19 +46,23 @@ namespace cpp {
|
||||
|
||||
class StringFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
explicit StringFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
StringFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~StringFieldGenerator();
|
||||
|
||||
// implements 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 GenerateMessageClearingCode(io::Printer* printer) const;
|
||||
void GenerateMergingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const;
|
||||
void GenerateDestructorCode(io::Printer* printer) const;
|
||||
void GenerateDefaultInstanceAllocator(io::Printer* printer) const;
|
||||
void GenerateShutdownCode(io::Printer* printer) const;
|
||||
@@ -67,27 +71,54 @@ class StringFieldGenerator : public FieldGenerator {
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
protected:
|
||||
const FieldDescriptor* descriptor_;
|
||||
map<string, string> variables_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator);
|
||||
};
|
||||
|
||||
class StringOneofFieldGenerator : public StringFieldGenerator {
|
||||
public:
|
||||
StringOneofFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~StringOneofFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer,
|
||||
bool is_inline) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
|
||||
// StringFieldGenerator, from which we inherit, overrides this so we need to
|
||||
// override it as well.
|
||||
void GenerateMessageClearingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateDestructorCode(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
const bool dependent_field_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator);
|
||||
};
|
||||
|
||||
class RepeatedStringFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~RepeatedStringFieldGenerator();
|
||||
|
||||
// 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;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateCopyConstructorCode(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
@@ -95,7 +126,7 @@ class RepeatedStringFieldGenerator : public FieldGenerator {
|
||||
|
||||
private:
|
||||
const FieldDescriptor* descriptor_;
|
||||
map<string, string> variables_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator);
|
||||
};
|
||||
+41
-8
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -35,6 +35,7 @@
|
||||
// This file tests that various identifiers work as field and type names even
|
||||
// though the same identifiers are used internally by the C++ code generator.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
// Some generic_services option(s) added automatically.
|
||||
// See: http://go/proto2-generic-services-default
|
||||
@@ -58,7 +59,7 @@ message TestConflictingSymbolNames {
|
||||
optional int32 total_size = 6;
|
||||
optional int32 tag = 7;
|
||||
|
||||
enum TestEnum { FOO = 1; }
|
||||
enum TestEnum { FOO = 0; }
|
||||
message Data1 { repeated int32 data = 1; }
|
||||
message Data2 { repeated TestEnum data = 1; }
|
||||
message Data3 { repeated string data = 1; }
|
||||
@@ -98,6 +99,9 @@ message TestConflictingSymbolNames {
|
||||
// Some keywords.
|
||||
optional uint32 int = 30;
|
||||
optional uint32 friend = 31;
|
||||
optional uint32 class = 37;
|
||||
optional uint32 typedecl = 39;
|
||||
optional uint32 auto = 40;
|
||||
|
||||
// The generator used to #define a macro called "DO" inside the .cc file.
|
||||
message DO {}
|
||||
@@ -107,14 +111,43 @@ message TestConflictingSymbolNames {
|
||||
optional int32 field_type = 33;
|
||||
optional bool is_packed = 34;
|
||||
|
||||
extensions 1000 to max;
|
||||
// test conflicting release_$name$. "length" and "do" field in this message
|
||||
// must remain string or message fields to make the test valid.
|
||||
optional string release_length = 35;
|
||||
// A more extreme case, the field name "do" here is a keyword, which will be
|
||||
// escaped to "do_" already. Test there is no conflict even with escaped field
|
||||
// names.
|
||||
optional DO release_do = 36;
|
||||
|
||||
// For clashing local variables in Serialize and ByteSize calculation.
|
||||
optional string target = 38;
|
||||
|
||||
extensions 1000 to max; // NO_PROTO3
|
||||
}
|
||||
|
||||
message TestConflictingSymbolNamesExtension {
|
||||
extend TestConflictingSymbolNames {
|
||||
repeated int32 repeated_int32_ext = 20423638 [packed=true];
|
||||
}
|
||||
}
|
||||
message TestConflictingSymbolNamesExtension { // NO_PROTO3
|
||||
extend TestConflictingSymbolNames { // NO_PROTO3
|
||||
repeated int32 repeated_int32_ext = 20423638 [packed=true]; // NO_PROTO3
|
||||
} // NO_PROTO3
|
||||
} // NO_PROTO3
|
||||
|
||||
message TestConflictingEnumNames { // NO_PROTO3
|
||||
enum NestedConflictingEnum { // NO_PROTO3
|
||||
and = 1; // NO_PROTO3
|
||||
class = 2; // NO_PROTO3
|
||||
int = 3; // NO_PROTO3
|
||||
typedef = 4; // NO_PROTO3
|
||||
XOR = 5; // NO_PROTO3
|
||||
} // NO_PROTO3
|
||||
|
||||
optional NestedConflictingEnum conflicting_enum = 1; // NO_PROTO3
|
||||
} // NO_PROTO3
|
||||
|
||||
enum ConflictingEnum { // NO_PROTO3
|
||||
NOT_EQ = 1; // NO_PROTO3
|
||||
volatile = 2; // NO_PROTO3
|
||||
return = 3; // NO_PROTO3
|
||||
} // NO_PROTO3
|
||||
|
||||
message DummyMessage {}
|
||||
|
||||
+43
@@ -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;
|
||||
}
|
||||
}
|
||||
+874
-20
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1,6 +1,6 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
// 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
|
||||
@@ -0,0 +1,242 @@
|
||||
// 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 <memory>
|
||||
#ifndef _SHARED_PTR_H
|
||||
#include <google/protobuf/stubs/shared_ptr.h>
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_generator.h>
|
||||
#include <google/protobuf/compiler/command_line_interface.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/testing/file.h>
|
||||
#include <google/protobuf/testing/googletest.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
namespace {
|
||||
|
||||
// A CodeGenerator that captures the FileDescriptor it's passed as a
|
||||
// FileDescriptorProto.
|
||||
class DescriptorCapturingGenerator : public CodeGenerator {
|
||||
public:
|
||||
// Does not own file; file must outlive the Generator.
|
||||
explicit DescriptorCapturingGenerator(FileDescriptorProto* file)
|
||||
: file_(file) {}
|
||||
|
||||
virtual bool Generate(const FileDescriptor* file, const string& parameter,
|
||||
GeneratorContext* context, string* error) const {
|
||||
file->CopyTo(file_);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
FileDescriptorProto* file_;
|
||||
};
|
||||
|
||||
class CppMetadataTest : public ::testing::Test {
|
||||
public:
|
||||
// Adds a file with name `filename` and content `data`.
|
||||
void AddFile(const string& filename, const string& data) {
|
||||
GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/" + filename, data,
|
||||
true));
|
||||
}
|
||||
|
||||
// Tries to capture a FileDescriptorProto, GeneratedCodeInfo, and output
|
||||
// code from the previously added file with name `filename`. Returns true on
|
||||
// success. If pb_h is non-null, expects a .pb.h and a .pb.h.meta (copied to
|
||||
// pb_h and pb_h_info respecfively); similarly for proto_h and proto_h_info.
|
||||
bool CaptureMetadata(const string& filename, FileDescriptorProto* file,
|
||||
string* pb_h, GeneratedCodeInfo* pb_h_info,
|
||||
string* proto_h, GeneratedCodeInfo* proto_h_info,
|
||||
string* pb_cc) {
|
||||
google::protobuf::compiler::CommandLineInterface cli;
|
||||
cli.SetInputsAreProtoPathRelative(true);
|
||||
|
||||
CppGenerator cpp_generator;
|
||||
DescriptorCapturingGenerator capturing_generator(file);
|
||||
cli.RegisterGenerator("--cpp_out", &cpp_generator, "");
|
||||
cli.RegisterGenerator("--capture_out", &capturing_generator, "");
|
||||
|
||||
string proto_path = "-I" + TestTempDir();
|
||||
string cpp_out =
|
||||
"--cpp_out=annotate_headers=true,"
|
||||
"annotation_pragma_name=pragma_name,"
|
||||
"annotation_guard_name=guard_name:" +
|
||||
TestTempDir();
|
||||
string capture_out = "--capture_out=" + TestTempDir();
|
||||
|
||||
const char* argv[] = {"protoc", proto_path.c_str(), cpp_out.c_str(),
|
||||
capture_out.c_str(), filename.c_str()};
|
||||
|
||||
if (cli.Run(5, argv) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string output_base = TestTempDir() + "/" + StripProto(filename);
|
||||
|
||||
if (pb_cc != NULL) {
|
||||
GOOGLE_CHECK_OK(
|
||||
File::GetContents(output_base + ".pb.cc", pb_cc, true));
|
||||
}
|
||||
|
||||
if (pb_h != NULL && pb_h_info != NULL) {
|
||||
GOOGLE_CHECK_OK(
|
||||
File::GetContents(output_base + ".pb.h", pb_h, true));
|
||||
if (!DecodeMetadata(output_base + ".pb.h.meta", pb_h_info)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (proto_h != NULL && proto_h_info != NULL) {
|
||||
GOOGLE_CHECK_OK(File::GetContents(output_base + ".proto.h", proto_h,
|
||||
true));
|
||||
if (!DecodeMetadata(output_base + ".proto.h.meta", proto_h_info)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
// Decodes GeneratedCodeInfo stored in path and copies it to info.
|
||||
// Returns true on success.
|
||||
bool DecodeMetadata(const string& path, GeneratedCodeInfo* info) {
|
||||
string data;
|
||||
GOOGLE_CHECK_OK(File::GetContents(path, &data, true));
|
||||
io::ArrayInputStream input(data.data(), data.size());
|
||||
return info->ParseFromZeroCopyStream(&input);
|
||||
}
|
||||
};
|
||||
|
||||
const char kSmallTestFile[] =
|
||||
"syntax = \"proto2\";\n"
|
||||
"package foo;\n"
|
||||
"enum Enum { VALUE = 0; }\n"
|
||||
"message Message { }\n";
|
||||
|
||||
// Finds the Annotation for a given source file and path (or returns null if it
|
||||
// couldn't).
|
||||
const GeneratedCodeInfo::Annotation* FindAnnotationOnPath(
|
||||
const GeneratedCodeInfo& info, const string& source_file,
|
||||
const std::vector<int>& path) {
|
||||
for (int i = 0; i < info.annotation_size(); ++i) {
|
||||
const GeneratedCodeInfo::Annotation* annotation = &info.annotation(i);
|
||||
if (annotation->source_file() != source_file ||
|
||||
annotation->path_size() != path.size()) {
|
||||
continue;
|
||||
}
|
||||
int node = 0;
|
||||
for (; node < path.size(); ++node) {
|
||||
if (annotation->path(node) != path[node]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (node == path.size()) {
|
||||
return annotation;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Returns true if the provided annotation covers a given substring in
|
||||
// file_content.
|
||||
bool AnnotationMatchesSubstring(const string& file_content,
|
||||
const GeneratedCodeInfo::Annotation* annotation,
|
||||
const string& expected_text) {
|
||||
uint32 begin = annotation->begin();
|
||||
uint32 end = annotation->end();
|
||||
if (end < begin || end > file_content.size()) {
|
||||
return false;
|
||||
}
|
||||
return file_content.substr(begin, end - begin) == expected_text;
|
||||
}
|
||||
|
||||
TEST_F(CppMetadataTest, CapturesEnumNames) {
|
||||
FileDescriptorProto file;
|
||||
GeneratedCodeInfo info;
|
||||
string pb_h;
|
||||
AddFile("test.proto", kSmallTestFile);
|
||||
EXPECT_TRUE(
|
||||
CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
|
||||
EXPECT_EQ("Enum", file.enum_type(0).name());
|
||||
std::vector<int> enum_path;
|
||||
enum_path.push_back(FileDescriptorProto::kEnumTypeFieldNumber);
|
||||
enum_path.push_back(0);
|
||||
const GeneratedCodeInfo::Annotation* enum_annotation =
|
||||
FindAnnotationOnPath(info, "test.proto", enum_path);
|
||||
EXPECT_TRUE(NULL != enum_annotation);
|
||||
EXPECT_TRUE(AnnotationMatchesSubstring(pb_h, enum_annotation, "Enum"));
|
||||
}
|
||||
|
||||
TEST_F(CppMetadataTest, AddsPragma) {
|
||||
FileDescriptorProto file;
|
||||
GeneratedCodeInfo info;
|
||||
string pb_h;
|
||||
AddFile("test.proto", kSmallTestFile);
|
||||
EXPECT_TRUE(
|
||||
CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
|
||||
EXPECT_TRUE(pb_h.find("#ifdef guard_name") != string::npos);
|
||||
EXPECT_TRUE(pb_h.find("#pragma pragma_name \"test.pb.h.meta\"") !=
|
||||
string::npos);
|
||||
}
|
||||
|
||||
TEST_F(CppMetadataTest, CapturesMessageNames) {
|
||||
FileDescriptorProto file;
|
||||
GeneratedCodeInfo info;
|
||||
string pb_h;
|
||||
AddFile("test.proto", kSmallTestFile);
|
||||
EXPECT_TRUE(
|
||||
CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL));
|
||||
EXPECT_EQ("Message", file.message_type(0).name());
|
||||
std::vector<int> message_path;
|
||||
message_path.push_back(FileDescriptorProto::kMessageTypeFieldNumber);
|
||||
message_path.push_back(0);
|
||||
const GeneratedCodeInfo::Annotation* message_annotation =
|
||||
FindAnnotationOnPath(info, "test.proto", message_path);
|
||||
EXPECT_TRUE(NULL != message_annotation);
|
||||
EXPECT_TRUE(AnnotationMatchesSubstring(pb_h, message_annotation, "Message"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -0,0 +1,114 @@
|
||||
// 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.
|
||||
#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
// Functions to create C# XML documentation comments.
|
||||
// Currently this only includes documentation comments containing text specified as comments
|
||||
// in the .proto file; documentation comments generated just from field/message/enum/proto names
|
||||
// is inlined in the relevant code. If more control is required, that code can be moved here.
|
||||
|
||||
void WriteDocCommentBodyImpl(io::Printer* printer, SourceLocation location) {
|
||||
string comments = location.leading_comments.empty() ?
|
||||
location.trailing_comments : location.leading_comments;
|
||||
if (comments.empty()) {
|
||||
return;
|
||||
}
|
||||
// XML escaping... no need for apostrophes etc as the whole text is going to be a child
|
||||
// node of a summary element, not part of an attribute.
|
||||
comments = StringReplace(comments, "&", "&", true);
|
||||
comments = StringReplace(comments, "<", "<", true);
|
||||
vector<string> lines = Split(comments, "\n", false /* skip_empty */);
|
||||
// TODO: We really should work out which part to put in the summary and which to put in the remarks...
|
||||
// but that needs to be part of a bigger effort to understand the markdown better anyway.
|
||||
printer->Print("/// <summary>\n");
|
||||
bool last_was_empty = false;
|
||||
// We squash multiple blank lines down to one, and remove any trailing blank lines. We need
|
||||
// to preserve the blank lines themselves, as this is relevant in the markdown.
|
||||
// Note that we can't remove leading or trailing whitespace as *that's* relevant in markdown too.
|
||||
// (We don't skip "just whitespace" lines, either.)
|
||||
for (std::vector<string>::iterator it = lines.begin(); it != lines.end(); ++it) {
|
||||
string line = *it;
|
||||
if (line.empty()) {
|
||||
last_was_empty = true;
|
||||
} else {
|
||||
if (last_was_empty) {
|
||||
printer->Print("///\n");
|
||||
}
|
||||
last_was_empty = false;
|
||||
printer->Print("///$line$\n", "line", *it);
|
||||
}
|
||||
}
|
||||
printer->Print("/// </summary>\n");
|
||||
}
|
||||
|
||||
template <typename DescriptorType>
|
||||
static void WriteDocCommentBody(
|
||||
io::Printer* printer, const DescriptorType* descriptor) {
|
||||
SourceLocation location;
|
||||
if (descriptor->GetSourceLocation(&location)) {
|
||||
WriteDocCommentBodyImpl(printer, location);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) {
|
||||
WriteDocCommentBody(printer, message);
|
||||
}
|
||||
|
||||
void WritePropertyDocComment(io::Printer* printer, const FieldDescriptor* field) {
|
||||
WriteDocCommentBody(printer, field);
|
||||
}
|
||||
|
||||
void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enumDescriptor) {
|
||||
WriteDocCommentBody(printer, enumDescriptor);
|
||||
}
|
||||
void WriteEnumValueDocComment(io::Printer* printer, const EnumValueDescriptor* value) {
|
||||
WriteDocCommentBody(printer, value);
|
||||
}
|
||||
|
||||
void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method) {
|
||||
WriteDocCommentBody(printer, method);
|
||||
}
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -0,0 +1,51 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__
|
||||
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
void WriteMessageDocComment(io::Printer* printer, const Descriptor* message);
|
||||
void WritePropertyDocComment(io::Printer* printer, const FieldDescriptor* field);
|
||||
void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enumDescriptor);
|
||||
void WriteEnumValueDocComment(io::Printer* printer, const EnumValueDescriptor* value);
|
||||
void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method);
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__
|
||||
@@ -0,0 +1,92 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <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/stubs/strutil.h>
|
||||
|
||||
#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_enum.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_options.h>
|
||||
|
||||
using google::protobuf::internal::scoped_ptr;
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Options* options) :
|
||||
SourceGeneratorBase(descriptor->file(), options),
|
||||
descriptor_(descriptor) {
|
||||
}
|
||||
|
||||
EnumGenerator::~EnumGenerator() {
|
||||
}
|
||||
|
||||
void EnumGenerator::Generate(io::Printer* printer) {
|
||||
WriteEnumDocComment(printer, descriptor_);
|
||||
printer->Print("$access_level$ enum $name$ {\n",
|
||||
"access_level", class_access_level(),
|
||||
"name", descriptor_->name());
|
||||
printer->Indent();
|
||||
std::set<string> used_names;
|
||||
for (int i = 0; i < descriptor_->value_count(); i++) {
|
||||
WriteEnumValueDocComment(printer, descriptor_->value(i));
|
||||
string original_name = descriptor_->value(i)->name();
|
||||
string name = GetEnumValueName(descriptor_->name(), descriptor_->value(i)->name());
|
||||
// Make sure we don't get any duplicate names due to prefix removal.
|
||||
while (!used_names.insert(name).second) {
|
||||
// It's possible we'll end up giving this warning multiple times, but that's better than not at all.
|
||||
GOOGLE_LOG(WARNING) << "Duplicate enum value " << name << " (originally " << original_name
|
||||
<< ") in " << descriptor_->name() << "; adding underscore to distinguish";
|
||||
name += "_";
|
||||
}
|
||||
printer->Print("[pbr::OriginalName(\"$original_name$\")] $name$ = $number$,\n",
|
||||
"original_name", original_name,
|
||||
"name", name,
|
||||
"number", SimpleItoa(descriptor_->value(i)->number()));
|
||||
}
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
printer->Print("\n");
|
||||
}
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -0,0 +1,63 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
class EnumGenerator : public SourceGeneratorBase {
|
||||
public:
|
||||
EnumGenerator(const EnumDescriptor* descriptor, const Options* options);
|
||||
~EnumGenerator();
|
||||
|
||||
void Generate(io::Printer* printer);
|
||||
|
||||
private:
|
||||
const EnumDescriptor* descriptor_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
|
||||
};
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
// 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/csharp/csharp_helpers.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_options.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_enum_field.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||
int fieldOrdinal, const Options *options)
|
||||
: PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) {
|
||||
}
|
||||
|
||||
EnumFieldGenerator::~EnumFieldGenerator() {
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
|
||||
printer->Print(variables_,
|
||||
"$name$_ = ($type_name$) input.ReadEnum();\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
|
||||
printer->Print(variables_,
|
||||
"if ($has_property_check$) {\n"
|
||||
" output.WriteRawTag($tag_bytes$);\n"
|
||||
" output.WriteEnum((int) $property_name$);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"if ($has_property_check$) {\n"
|
||||
" size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::GenerateCodecCode(io::Printer* printer) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x)");
|
||||
}
|
||||
|
||||
EnumOneofFieldGenerator::EnumOneofFieldGenerator(
|
||||
const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
|
||||
: PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options) {
|
||||
}
|
||||
|
||||
EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {
|
||||
}
|
||||
|
||||
void EnumOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
|
||||
// TODO(jonskeet): What about if we read the default value?
|
||||
printer->Print(
|
||||
variables_,
|
||||
"$oneof_name$_ = input.ReadEnum();\n"
|
||||
"$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n");
|
||||
}
|
||||
|
||||
void EnumOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"if ($has_property_check$) {\n"
|
||||
" output.WriteRawTag($tag_bytes$);\n"
|
||||
" output.WriteEnum((int) $property_name$);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"if ($has_property_check$) {\n"
|
||||
" size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -0,0 +1,81 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
class EnumFieldGenerator : public PrimitiveFieldGenerator {
|
||||
public:
|
||||
EnumFieldGenerator(const FieldDescriptor* descriptor,
|
||||
int fieldOrdinal,
|
||||
const Options *options);
|
||||
~EnumFieldGenerator();
|
||||
|
||||
virtual void GenerateCodecCode(io::Printer* printer);
|
||||
virtual void GenerateParsingCode(io::Printer* printer);
|
||||
virtual void GenerateSerializationCode(io::Printer* printer);
|
||||
virtual void GenerateSerializedSizeCode(io::Printer* printer);
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
|
||||
};
|
||||
|
||||
class EnumOneofFieldGenerator : public PrimitiveOneofFieldGenerator {
|
||||
public:
|
||||
EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
|
||||
int fieldOrdinal,
|
||||
const Options *options);
|
||||
~EnumOneofFieldGenerator();
|
||||
|
||||
virtual void GenerateParsingCode(io::Printer* printer);
|
||||
virtual void GenerateSerializationCode(io::Printer* printer);
|
||||
virtual void GenerateSerializedSizeCode(io::Printer* printer);
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator);
|
||||
};
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__
|
||||
|
||||
@@ -0,0 +1,430 @@
|
||||
// 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 <limits>
|
||||
#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/coded_stream.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/stubs/mathlimits.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
|
||||
#include <google/protobuf/compiler/csharp/csharp_field_base.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_names.h>
|
||||
|
||||
using google::protobuf::internal::scoped_ptr;
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
void FieldGeneratorBase::SetCommonFieldVariables(
|
||||
map<string, string>* variables) {
|
||||
// Note: this will be valid even though the tag emitted for packed and unpacked versions of
|
||||
// repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which
|
||||
// never effects the tag size.
|
||||
int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
|
||||
uint tag = internal::WireFormat::MakeTag(descriptor_);
|
||||
uint8 tag_array[5];
|
||||
io::CodedOutputStream::WriteTagToArray(tag, tag_array);
|
||||
string tag_bytes = SimpleItoa(tag_array[0]);
|
||||
for (int i = 1; i < tag_size; i++) {
|
||||
tag_bytes += ", " + SimpleItoa(tag_array[i]);
|
||||
}
|
||||
|
||||
(*variables)["access_level"] = "public";
|
||||
(*variables)["tag"] = SimpleItoa(tag);
|
||||
(*variables)["tag_size"] = SimpleItoa(tag_size);
|
||||
(*variables)["tag_bytes"] = tag_bytes;
|
||||
|
||||
(*variables)["property_name"] = property_name();
|
||||
(*variables)["type_name"] = type_name();
|
||||
(*variables)["name"] = name();
|
||||
(*variables)["descriptor_name"] = descriptor_->name();
|
||||
(*variables)["default_value"] = default_value();
|
||||
if (has_default_value()) {
|
||||
(*variables)["name_def_message"] =
|
||||
(*variables)["name"] + "_ = " + (*variables)["default_value"];
|
||||
} else {
|
||||
(*variables)["name_def_message"] = (*variables)["name"] + "_";
|
||||
}
|
||||
(*variables)["capitalized_type_name"] = capitalized_type_name();
|
||||
(*variables)["number"] = number();
|
||||
(*variables)["has_property_check"] =
|
||||
(*variables)["property_name"] + " != " + (*variables)["default_value"];
|
||||
(*variables)["other_has_property_check"] = "other." +
|
||||
(*variables)["property_name"] + " != " + (*variables)["default_value"];
|
||||
}
|
||||
|
||||
void FieldGeneratorBase::SetCommonOneofFieldVariables(
|
||||
map<string, string>* variables) {
|
||||
(*variables)["oneof_name"] = oneof_name();
|
||||
(*variables)["has_property_check"] =
|
||||
oneof_name() + "Case_ == " + oneof_property_name() +
|
||||
"OneofCase." + property_name();
|
||||
(*variables)["oneof_property_name"] = oneof_property_name();
|
||||
}
|
||||
|
||||
FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor,
|
||||
int fieldOrdinal, const Options* options)
|
||||
: SourceGeneratorBase(descriptor->file(), options),
|
||||
descriptor_(descriptor),
|
||||
fieldOrdinal_(fieldOrdinal) {
|
||||
SetCommonFieldVariables(&variables_);
|
||||
}
|
||||
|
||||
FieldGeneratorBase::~FieldGeneratorBase() {
|
||||
}
|
||||
|
||||
void FieldGeneratorBase::GenerateFreezingCode(io::Printer* printer) {
|
||||
// No-op: only message fields and repeated fields need
|
||||
// special handling for freezing, so default to not generating any code.
|
||||
}
|
||||
|
||||
void FieldGeneratorBase::GenerateCodecCode(io::Printer* printer) {
|
||||
// No-op: expect this to be overridden by appropriate types.
|
||||
// Could fail if we get called here though...
|
||||
}
|
||||
|
||||
void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) {
|
||||
if (descriptor_->options().deprecated())
|
||||
{
|
||||
printer->Print("[global::System.ObsoleteAttribute]\n");
|
||||
}
|
||||
}
|
||||
|
||||
void FieldGeneratorBase::AddPublicMemberAttributes(io::Printer* printer) {
|
||||
AddDeprecatedFlag(printer);
|
||||
WriteGeneratedCodeAttributes(printer);
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::oneof_property_name() {
|
||||
return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), true);
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::oneof_name() {
|
||||
return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), false);
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::property_name() {
|
||||
return GetPropertyName(descriptor_);
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::name() {
|
||||
return UnderscoresToCamelCase(GetFieldName(descriptor_), false);
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::type_name() {
|
||||
return type_name(descriptor_);
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::type_name(const FieldDescriptor* descriptor) {
|
||||
switch (descriptor->type()) {
|
||||
case FieldDescriptor::TYPE_ENUM:
|
||||
return GetClassName(descriptor->enum_type());
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
if (IsWrapperType(descriptor)) {
|
||||
const FieldDescriptor* wrapped_field =
|
||||
descriptor->message_type()->field(0);
|
||||
string wrapped_field_type_name = type_name(wrapped_field);
|
||||
// String and ByteString go to the same type; other wrapped types
|
||||
// go to the nullable equivalent.
|
||||
if (wrapped_field->type() == FieldDescriptor::TYPE_STRING ||
|
||||
wrapped_field->type() == FieldDescriptor::TYPE_BYTES) {
|
||||
return wrapped_field_type_name;
|
||||
} else {
|
||||
return wrapped_field_type_name + "?";
|
||||
}
|
||||
}
|
||||
return GetClassName(descriptor->message_type());
|
||||
case FieldDescriptor::TYPE_DOUBLE:
|
||||
return "double";
|
||||
case FieldDescriptor::TYPE_FLOAT:
|
||||
return "float";
|
||||
case FieldDescriptor::TYPE_INT64:
|
||||
return "long";
|
||||
case FieldDescriptor::TYPE_UINT64:
|
||||
return "ulong";
|
||||
case FieldDescriptor::TYPE_INT32:
|
||||
return "int";
|
||||
case FieldDescriptor::TYPE_FIXED64:
|
||||
return "ulong";
|
||||
case FieldDescriptor::TYPE_FIXED32:
|
||||
return "uint";
|
||||
case FieldDescriptor::TYPE_BOOL:
|
||||
return "bool";
|
||||
case FieldDescriptor::TYPE_STRING:
|
||||
return "string";
|
||||
case FieldDescriptor::TYPE_BYTES:
|
||||
return "pb::ByteString";
|
||||
case FieldDescriptor::TYPE_UINT32:
|
||||
return "uint";
|
||||
case FieldDescriptor::TYPE_SFIXED32:
|
||||
return "int";
|
||||
case FieldDescriptor::TYPE_SFIXED64:
|
||||
return "long";
|
||||
case FieldDescriptor::TYPE_SINT32:
|
||||
return "int";
|
||||
case FieldDescriptor::TYPE_SINT64:
|
||||
return "long";
|
||||
default:
|
||||
GOOGLE_LOG(FATAL)<< "Unknown field type.";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
bool FieldGeneratorBase::has_default_value() {
|
||||
switch (descriptor_->type()) {
|
||||
case FieldDescriptor::TYPE_ENUM:
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
return true;
|
||||
case FieldDescriptor::TYPE_DOUBLE:
|
||||
return descriptor_->default_value_double() != 0.0;
|
||||
case FieldDescriptor::TYPE_FLOAT:
|
||||
return descriptor_->default_value_float() != 0.0;
|
||||
case FieldDescriptor::TYPE_INT64:
|
||||
return descriptor_->default_value_int64() != 0L;
|
||||
case FieldDescriptor::TYPE_UINT64:
|
||||
return descriptor_->default_value_uint64() != 0L;
|
||||
case FieldDescriptor::TYPE_INT32:
|
||||
return descriptor_->default_value_int32() != 0;
|
||||
case FieldDescriptor::TYPE_FIXED64:
|
||||
return descriptor_->default_value_uint64() != 0L;
|
||||
case FieldDescriptor::TYPE_FIXED32:
|
||||
return descriptor_->default_value_uint32() != 0;
|
||||
case FieldDescriptor::TYPE_BOOL:
|
||||
return descriptor_->default_value_bool();
|
||||
case FieldDescriptor::TYPE_STRING:
|
||||
return true;
|
||||
case FieldDescriptor::TYPE_BYTES:
|
||||
return true;
|
||||
case FieldDescriptor::TYPE_UINT32:
|
||||
return descriptor_->default_value_uint32() != 0;
|
||||
case FieldDescriptor::TYPE_SFIXED32:
|
||||
return descriptor_->default_value_int32() != 0;
|
||||
case FieldDescriptor::TYPE_SFIXED64:
|
||||
return descriptor_->default_value_int64() != 0L;
|
||||
case FieldDescriptor::TYPE_SINT32:
|
||||
return descriptor_->default_value_int32() != 0;
|
||||
case FieldDescriptor::TYPE_SINT64:
|
||||
return descriptor_->default_value_int64() != 0L;
|
||||
default:
|
||||
GOOGLE_LOG(FATAL)<< "Unknown field type.";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool FieldGeneratorBase::is_nullable_type() {
|
||||
switch (descriptor_->type()) {
|
||||
case FieldDescriptor::TYPE_ENUM:
|
||||
case FieldDescriptor::TYPE_DOUBLE:
|
||||
case FieldDescriptor::TYPE_FLOAT:
|
||||
case FieldDescriptor::TYPE_INT64:
|
||||
case FieldDescriptor::TYPE_UINT64:
|
||||
case FieldDescriptor::TYPE_INT32:
|
||||
case FieldDescriptor::TYPE_FIXED64:
|
||||
case FieldDescriptor::TYPE_FIXED32:
|
||||
case FieldDescriptor::TYPE_BOOL:
|
||||
case FieldDescriptor::TYPE_UINT32:
|
||||
case FieldDescriptor::TYPE_SFIXED32:
|
||||
case FieldDescriptor::TYPE_SFIXED64:
|
||||
case FieldDescriptor::TYPE_SINT32:
|
||||
case FieldDescriptor::TYPE_SINT64:
|
||||
return false;
|
||||
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
case FieldDescriptor::TYPE_STRING:
|
||||
case FieldDescriptor::TYPE_BYTES:
|
||||
return true;
|
||||
|
||||
default:
|
||||
GOOGLE_LOG(FATAL)<< "Unknown field type.";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool AllPrintableAscii(const std::string& text) {
|
||||
for(int i = 0; i < text.size(); i++) {
|
||||
if (text[i] < 0x20 || text[i] > 0x7e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::GetStringDefaultValueInternal() {
|
||||
// No other default values needed for proto3...
|
||||
return "\"\"";
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::GetBytesDefaultValueInternal() {
|
||||
// No other default values needed for proto3...
|
||||
return "pb::ByteString.Empty";
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::default_value() {
|
||||
return default_value(descriptor_);
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) {
|
||||
switch (descriptor->type()) {
|
||||
case FieldDescriptor::TYPE_ENUM:
|
||||
// All proto3 enums have a default value of 0, and there's an implicit conversion from the constant 0 to
|
||||
// any C# enum. This means we don't need to work out what we actually mapped the enum value name to.
|
||||
return "0";
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
if (IsWrapperType(descriptor)) {
|
||||
const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
|
||||
return default_value(wrapped_field);
|
||||
} else {
|
||||
return "null";
|
||||
}
|
||||
case FieldDescriptor::TYPE_DOUBLE: {
|
||||
double value = descriptor->default_value_double();
|
||||
if (value == numeric_limits<double>::infinity()) {
|
||||
return "double.PositiveInfinity";
|
||||
} else if (value == -numeric_limits<double>::infinity()) {
|
||||
return "double.NegativeInfinity";
|
||||
} else if (MathLimits<double>::IsNaN(value)) {
|
||||
return "double.NaN";
|
||||
}
|
||||
return SimpleDtoa(value) + "D";
|
||||
}
|
||||
case FieldDescriptor::TYPE_FLOAT: {
|
||||
float value = descriptor->default_value_float();
|
||||
if (value == numeric_limits<float>::infinity()) {
|
||||
return "float.PositiveInfinity";
|
||||
} else if (value == -numeric_limits<float>::infinity()) {
|
||||
return "float.NegativeInfinity";
|
||||
} else if (MathLimits<float>::IsNaN(value)) {
|
||||
return "float.NaN";
|
||||
}
|
||||
return SimpleFtoa(value) + "F";
|
||||
}
|
||||
case FieldDescriptor::TYPE_INT64:
|
||||
return SimpleItoa(descriptor->default_value_int64()) + "L";
|
||||
case FieldDescriptor::TYPE_UINT64:
|
||||
return SimpleItoa(descriptor->default_value_uint64()) + "UL";
|
||||
case FieldDescriptor::TYPE_INT32:
|
||||
return SimpleItoa(descriptor->default_value_int32());
|
||||
case FieldDescriptor::TYPE_FIXED64:
|
||||
return SimpleItoa(descriptor->default_value_uint64()) + "UL";
|
||||
case FieldDescriptor::TYPE_FIXED32:
|
||||
return SimpleItoa(descriptor->default_value_uint32());
|
||||
case FieldDescriptor::TYPE_BOOL:
|
||||
if (descriptor->default_value_bool()) {
|
||||
return "true";
|
||||
} else {
|
||||
return "false";
|
||||
}
|
||||
case FieldDescriptor::TYPE_STRING:
|
||||
return GetStringDefaultValueInternal();
|
||||
case FieldDescriptor::TYPE_BYTES:
|
||||
return GetBytesDefaultValueInternal();
|
||||
case FieldDescriptor::TYPE_UINT32:
|
||||
return SimpleItoa(descriptor->default_value_uint32());
|
||||
case FieldDescriptor::TYPE_SFIXED32:
|
||||
return SimpleItoa(descriptor->default_value_int32());
|
||||
case FieldDescriptor::TYPE_SFIXED64:
|
||||
return SimpleItoa(descriptor->default_value_int64()) + "L";
|
||||
case FieldDescriptor::TYPE_SINT32:
|
||||
return SimpleItoa(descriptor->default_value_int32());
|
||||
case FieldDescriptor::TYPE_SINT64:
|
||||
return SimpleItoa(descriptor->default_value_int64()) + "L";
|
||||
default:
|
||||
GOOGLE_LOG(FATAL)<< "Unknown field type.";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::number() {
|
||||
return SimpleItoa(descriptor_->number());
|
||||
}
|
||||
|
||||
std::string FieldGeneratorBase::capitalized_type_name() {
|
||||
switch (descriptor_->type()) {
|
||||
case FieldDescriptor::TYPE_ENUM:
|
||||
return "Enum";
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
return "Message";
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
return "Group";
|
||||
case FieldDescriptor::TYPE_DOUBLE:
|
||||
return "Double";
|
||||
case FieldDescriptor::TYPE_FLOAT:
|
||||
return "Float";
|
||||
case FieldDescriptor::TYPE_INT64:
|
||||
return "Int64";
|
||||
case FieldDescriptor::TYPE_UINT64:
|
||||
return "UInt64";
|
||||
case FieldDescriptor::TYPE_INT32:
|
||||
return "Int32";
|
||||
case FieldDescriptor::TYPE_FIXED64:
|
||||
return "Fixed64";
|
||||
case FieldDescriptor::TYPE_FIXED32:
|
||||
return "Fixed32";
|
||||
case FieldDescriptor::TYPE_BOOL:
|
||||
return "Bool";
|
||||
case FieldDescriptor::TYPE_STRING:
|
||||
return "String";
|
||||
case FieldDescriptor::TYPE_BYTES:
|
||||
return "Bytes";
|
||||
case FieldDescriptor::TYPE_UINT32:
|
||||
return "UInt32";
|
||||
case FieldDescriptor::TYPE_SFIXED32:
|
||||
return "SFixed32";
|
||||
case FieldDescriptor::TYPE_SFIXED64:
|
||||
return "SFixed64";
|
||||
case FieldDescriptor::TYPE_SINT32:
|
||||
return "SInt32";
|
||||
case FieldDescriptor::TYPE_SINT64:
|
||||
return "SInt64";
|
||||
default:
|
||||
GOOGLE_LOG(FATAL)<< "Unknown field type.";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
class FieldGeneratorBase : public SourceGeneratorBase {
|
||||
public:
|
||||
FieldGeneratorBase(const FieldDescriptor* descriptor,
|
||||
int fieldOrdinal,
|
||||
const Options* options);
|
||||
~FieldGeneratorBase();
|
||||
|
||||
virtual void GenerateCloningCode(io::Printer* printer) = 0;
|
||||
virtual void GenerateFreezingCode(io::Printer* printer);
|
||||
virtual void GenerateCodecCode(io::Printer* printer);
|
||||
virtual void GenerateMembers(io::Printer* printer) = 0;
|
||||
virtual void GenerateMergingCode(io::Printer* printer) = 0;
|
||||
virtual void GenerateParsingCode(io::Printer* printer) = 0;
|
||||
virtual void GenerateSerializationCode(io::Printer* printer) = 0;
|
||||
virtual void GenerateSerializedSizeCode(io::Printer* printer) = 0;
|
||||
|
||||
virtual void WriteHash(io::Printer* printer) = 0;
|
||||
virtual void WriteEquals(io::Printer* printer) = 0;
|
||||
// Currently unused, as we use reflection to generate JSON
|
||||
virtual void WriteToString(io::Printer* printer) = 0;
|
||||
|
||||
protected:
|
||||
const FieldDescriptor* descriptor_;
|
||||
const int fieldOrdinal_;
|
||||
map<string, string> variables_;
|
||||
|
||||
void AddDeprecatedFlag(io::Printer* printer);
|
||||
void AddNullCheck(io::Printer* printer);
|
||||
void AddNullCheck(io::Printer* printer, const std::string& name);
|
||||
|
||||
void AddPublicMemberAttributes(io::Printer* printer);
|
||||
void SetCommonOneofFieldVariables(map<string, string>* variables);
|
||||
|
||||
std::string oneof_property_name();
|
||||
std::string oneof_name();
|
||||
std::string property_name();
|
||||
std::string name();
|
||||
std::string type_name();
|
||||
std::string type_name(const FieldDescriptor* descriptor);
|
||||
bool has_default_value();
|
||||
bool is_nullable_type();
|
||||
std::string default_value();
|
||||
std::string default_value(const FieldDescriptor* descriptor);
|
||||
std::string number();
|
||||
std::string capitalized_type_name();
|
||||
|
||||
private:
|
||||
void SetCommonFieldVariables(map<string, string>* variables);
|
||||
std::string GetStringDefaultValueInternal();
|
||||
std::string GetBytesDefaultValueInternal();
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorBase);
|
||||
};
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
// 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/stubs/strutil.h>
|
||||
|
||||
#include <google/protobuf/compiler/csharp/csharp_generator.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_names.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_options.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_reflection_class.h>
|
||||
|
||||
using google::protobuf::internal::scoped_ptr;
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace csharp {
|
||||
|
||||
void GenerateFile(const google::protobuf::FileDescriptor* file,
|
||||
io::Printer* printer,
|
||||
const Options* options) {
|
||||
ReflectionClassGenerator reflectionClassGenerator(file, options);
|
||||
reflectionClassGenerator.Generate(printer);
|
||||
}
|
||||
|
||||
bool Generator::Generate(
|
||||
const FileDescriptor* file,
|
||||
const string& parameter,
|
||||
GeneratorContext* generator_context,
|
||||
string* error) const {
|
||||
|
||||
vector<pair<string, string> > options;
|
||||
ParseGeneratorParameter(parameter, &options);
|
||||
|
||||
// We only support proto3 - but we make an exception for descriptor.proto.
|
||||
if (file->syntax() != FileDescriptor::SYNTAX_PROTO3 && !IsDescriptorProto(file)) {
|
||||
*error = "C# code generation only supports proto3 syntax";
|
||||
return false;
|
||||
}
|
||||
|
||||
struct Options cli_options;
|
||||
|
||||
for (int i = 0; i < options.size(); i++) {
|
||||
if (options[i].first == "file_extension") {
|
||||
cli_options.file_extension = options[i].second;
|
||||
} else if (options[i].first == "base_namespace") {
|
||||
cli_options.base_namespace = options[i].second;
|
||||
cli_options.base_namespace_specified = true;
|
||||
} else if (options[i].first == "internal_access") {
|
||||
cli_options.internal_access = true;
|
||||
} else {
|
||||
*error = "Unknown generator option: " + options[i].first;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
string filename_error = "";
|
||||
std::string filename = GetOutputFile(file,
|
||||
cli_options.file_extension,
|
||||
cli_options.base_namespace_specified,
|
||||
cli_options.base_namespace,
|
||||
&filename_error);
|
||||
|
||||
if (filename.empty()) {
|
||||
*error = filename_error;
|
||||
return false;
|
||||
}
|
||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
generator_context->Open(filename));
|
||||
io::Printer printer(output.get(), '$');
|
||||
|
||||
GenerateFile(file, &printer, &cli_options);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace csharp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user